aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Model/Dlna
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Model/Dlna')
-rw-r--r--MediaBrowser.Model/Dlna/ConditionProcessor.cs13
-rw-r--r--MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs4
-rw-r--r--MediaBrowser.Model/Dlna/DeviceProfile.cs4
-rw-r--r--MediaBrowser.Model/Dlna/ProfileCondition.cs1
-rw-r--r--MediaBrowser.Model/Dlna/ProfileConditionValue.cs3
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs289
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs32
7 files changed, 296 insertions, 50 deletions
diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
index a388bf98b..291096f75 100644
--- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs
+++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
@@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Dlna
public bool IsVideoConditionSatisfied(ProfileCondition condition,
int? width,
int? height,
- int? bitDepth,
+ int? videoBitDepth,
int? videoBitrate,
string videoProfile,
double? videoLevel,
@@ -46,7 +46,7 @@ namespace MediaBrowser.Model.Dlna
case ProfileConditionValue.PacketLength:
return IsConditionSatisfied(condition, packetLength);
case ProfileConditionValue.VideoBitDepth:
- return IsConditionSatisfied(condition, bitDepth);
+ return IsConditionSatisfied(condition, videoBitDepth);
case ProfileConditionValue.VideoBitrate:
return IsConditionSatisfied(condition, videoBitrate);
case ProfileConditionValue.Height:
@@ -79,7 +79,7 @@ namespace MediaBrowser.Model.Dlna
}
}
- public bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate)
+ public bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
{
switch (condition.Property)
{
@@ -89,6 +89,8 @@ namespace MediaBrowser.Model.Dlna
return IsConditionSatisfied(condition, audioChannels);
case ProfileConditionValue.AudioSampleRate:
return IsConditionSatisfied(condition, audioSampleRate);
+ case ProfileConditionValue.AudioBitDepth:
+ return IsConditionSatisfied(condition, audioBitDepth);
default:
throw new ArgumentException("Unexpected condition on audio file: " + condition.Property);
}
@@ -97,7 +99,8 @@ namespace MediaBrowser.Model.Dlna
public bool IsVideoAudioConditionSatisfied(ProfileCondition condition,
int? audioChannels,
int? audioBitrate,
- int? audioSampleRate,
+ int? audioSampleRate,
+ int? audioBitDepth,
string audioProfile,
bool? isSecondaryTrack)
{
@@ -113,6 +116,8 @@ namespace MediaBrowser.Model.Dlna
return IsConditionSatisfied(condition, isSecondaryTrack);
case ProfileConditionValue.AudioSampleRate:
return IsConditionSatisfied(condition, audioSampleRate);
+ case ProfileConditionValue.AudioBitDepth:
+ return IsConditionSatisfied(condition, audioBitDepth);
default:
throw new ArgumentException("Unexpected condition on audio file: " + condition.Property);
}
diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
index 6f6994a7e..8a9dc1dd1 100644
--- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
+++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
@@ -55,6 +55,7 @@ namespace MediaBrowser.Model.Dlna
int? audioBitrate,
int? audioSampleRate,
int? audioChannels,
+ int? audioBitDepth,
bool isDirectStream,
long? runtimeTicks,
TranscodeSeekInfo transcodeSeekInfo)
@@ -86,7 +87,8 @@ namespace MediaBrowser.Model.Dlna
audioCodec,
audioChannels,
audioBitrate,
- audioSampleRate);
+ audioSampleRate,
+ audioBitDepth);
string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs
index 33d73e3bb..cd7ff08d6 100644
--- a/MediaBrowser.Model/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs
@@ -185,7 +185,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate)
+ public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate, int? audioSampleRate, int? audioBitDepth)
{
container = StringHelper.TrimStart(container ?? string.Empty, '.');
@@ -213,7 +213,7 @@ namespace MediaBrowser.Model.Dlna
var anyOff = false;
foreach (ProfileCondition c in i.Conditions)
{
- if (!conditionProcessor.IsAudioConditionSatisfied(GetModelProfileCondition(c), audioChannels, audioBitrate, audioSampleRate))
+ if (!conditionProcessor.IsAudioConditionSatisfied(GetModelProfileCondition(c), audioChannels, audioBitrate, audioSampleRate, audioBitDepth))
{
anyOff = true;
break;
diff --git a/MediaBrowser.Model/Dlna/ProfileCondition.cs b/MediaBrowser.Model/Dlna/ProfileCondition.cs
index 3d104f9c4..9234a2713 100644
--- a/MediaBrowser.Model/Dlna/ProfileCondition.cs
+++ b/MediaBrowser.Model/Dlna/ProfileCondition.cs
@@ -1,5 +1,4 @@
using System.Xml.Serialization;
-using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Model.Dlna
{
diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs
index 208a7df7e..a96e9ac36 100644
--- a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs
+++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs
@@ -23,6 +23,7 @@
VideoCodecTag = 19,
IsAvc = 20,
IsInterlaced = 21,
- AudioSampleRate = 22
+ AudioSampleRate = 22,
+ AudioBitDepth = 23
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 0ecc413f2..342796a10 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -105,8 +105,102 @@ namespace MediaBrowser.Model.Dlna
return null;
}
+ private 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:
+ return TranscodeReason.AudioProfileNotSupported;
+
+ case ProfileConditionValue.AudioSampleRate:
+ return TranscodeReason.AudioSampleRateNotSupported;
+
+ case ProfileConditionValue.Has64BitOffsets:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.Height:
+ return TranscodeReason.VideoResolutionNotSupported;
+
+ case ProfileConditionValue.IsAnamorphic:
+ return TranscodeReason.AnamorphicVideoNotSupported;
+
+ case ProfileConditionValue.IsAvc:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.IsInterlaced:
+ return TranscodeReason.InterlacedVideoNotSupported;
+
+ case ProfileConditionValue.IsSecondaryAudio:
+ return TranscodeReason.SecondaryAudioNotSupported;
+
+ case ProfileConditionValue.NumAudioStreams:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.NumVideoStreams:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.PacketLength:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.RefFrames:
+ return TranscodeReason.RefFramesNotSupported;
+
+ case ProfileConditionValue.VideoBitDepth:
+ return TranscodeReason.VideoBitDepthNotSupported;
+
+ case ProfileConditionValue.AudioBitDepth:
+ return TranscodeReason.AudioBitDepthNotSupported;
+
+ case ProfileConditionValue.VideoBitrate:
+ return TranscodeReason.VideoBitrateNotSupported;
+
+ case ProfileConditionValue.VideoCodecTag:
+ return TranscodeReason.VideoCodecNotSupported;
+
+ case ProfileConditionValue.VideoFramerate:
+ return TranscodeReason.VideoFramerateNotSupported;
+
+ case ProfileConditionValue.VideoLevel:
+ return TranscodeReason.VideoLevelNotSupported;
+
+ case ProfileConditionValue.VideoProfile:
+ return TranscodeReason.VideoProfileNotSupported;
+
+ case ProfileConditionValue.VideoTimestamp:
+ // TODO
+ return null;
+
+ case ProfileConditionValue.Width:
+ return TranscodeReason.VideoResolutionNotSupported;
+
+ default:
+ return null;
+ }
+ }
+
private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
{
+ List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
+
StreamInfo playlistItem = new StreamInfo
{
ItemId = options.ItemId,
@@ -133,13 +227,17 @@ namespace MediaBrowser.Model.Dlna
MediaStream audioStream = item.GetDefaultAudioStream(null);
- List<PlayMethod> directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options);
+ var directPlayInfo = GetAudioDirectPlayMethods(item, audioStream, options);
+
+ List<PlayMethod> directPlayMethods = directPlayInfo.Item1;
+ transcodeReasons.AddRange(directPlayInfo.Item2);
ConditionProcessor conditionProcessor = new ConditionProcessor();
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;
if (directPlayMethods.Count > 0)
{
@@ -156,7 +254,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true;
foreach (ProfileCondition applyCondition in i.ApplyConditions)
{
- if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate))
+ if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth))
{
LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
applyConditions = false;
@@ -177,9 +275,14 @@ namespace MediaBrowser.Model.Dlna
bool all = true;
foreach (ProfileCondition c in conditions)
{
- if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate))
+ if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth))
{
LogConditionFailure(options.Profile, "AudioCodecProfile", c, item);
+ var transcodeReason = GetTranscodeReasonForFailedCondition(c);
+ if (transcodeReason.HasValue)
+ {
+ transcodeReasons.Add(transcodeReason.Value);
+ }
all = false;
break;
}
@@ -252,7 +355,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true;
foreach (ProfileCondition applyCondition in i.ApplyConditions)
{
- if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate))
+ if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth))
{
LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
applyConditions = false;
@@ -292,9 +395,9 @@ namespace MediaBrowser.Model.Dlna
var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
-
}
+ playlistItem.TranscodeReasons = transcodeReasons;
return playlistItem;
}
@@ -308,8 +411,10 @@ namespace MediaBrowser.Model.Dlna
return options.GetMaxBitrate(isAudio);
}
- private List<PlayMethod> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options)
+ private Tuple<List<PlayMethod>, List<TranscodeReason>> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options)
{
+ List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
+
DirectPlayProfile directPlayProfile = null;
foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles)
{
@@ -325,27 +430,134 @@ namespace MediaBrowser.Model.Dlna
if (directPlayProfile != null)
{
// While options takes the network and other factors into account. Only applies to direct stream
- if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream) && options.EnableDirectStream)
+ if (item.SupportsDirectStream)
{
- playMethods.Add(PlayMethod.DirectStream);
+ if (IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream))
+ {
+ if (options.EnableDirectStream)
+ {
+ 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 &&
- IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay) && options.EnableDirectPlay)
+ if (item.SupportsDirectPlay)
{
- playMethods.Add(PlayMethod.DirectPlay);
+ if (IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay))
+ {
+ if (options.EnableDirectPlay)
+ {
+ playMethods.Add(PlayMethod.DirectPlay);
+ }
+ }
+ else
+ {
+ transcodeReasons.Add(TranscodeReason.ContainerBitrateExceedsLimit);
+ }
}
}
else
{
+ transcodeReasons.InsertRange(0, GetTranscodeReasonsFromDirectPlayProfile(item, null, audioStream, options.Profile.DirectPlayProfiles));
+
_logger.Info("Profile: {0}, No direct play profiles found for Path: {1}",
options.Profile.Name ?? "Unknown Profile",
item.Path ?? "Unknown path");
}
- return playMethods;
+ if (playMethods.Count > 0)
+ {
+ transcodeReasons.Clear();
+ }
+ else
+ {
+ transcodeReasons = transcodeReasons.Distinct().ToList();
+ }
+
+ return new Tuple<List<PlayMethod>, List<TranscodeReason>>(playMethods, transcodeReasons);
+ }
+
+ private 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)
+ {
+ if (profile.Container.Length > 0)
+ {
+ // Check container type
+ string mediaContainer = item.Container ?? string.Empty;
+ foreach (string i in profile.GetContainers())
+ {
+ if (StringHelper.EqualsIgnoreCase(i, mediaContainer))
+ {
+ containerSupported = true;
+
+ if (videoStream != null)
+ {
+ // Check video codec
+ List<string> videoCodecs = profile.GetVideoCodecs();
+ if (videoCodecs.Count > 0)
+ {
+ string videoCodec = videoStream.Codec;
+ if (!string.IsNullOrEmpty(videoCodec) && ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec))
+ {
+ videoSupported = true;
+ }
+ }
+ else
+ {
+ videoSupported = true;
+ }
+ }
+
+ if (audioStream != null)
+ {
+ // Check audio codec
+ List<string> audioCodecs = profile.GetAudioCodecs();
+ if (audioCodecs.Count > 0)
+ {
+ string audioCodec = audioStream.Codec;
+ if (!string.IsNullOrEmpty(audioCodec) && ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec))
+ {
+ audioSupported = true;
+ }
+ }
+ else
+ {
+ audioSupported = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!containerSupported)
+ {
+ list.Add(TranscodeReason.ContainerNotSupported);
+ }
+
+ if (videoStream != null && !videoSupported)
+ {
+ list.Add(TranscodeReason.VideoCodecNotSupported);
+ }
+
+ if (audioStream != null && !audioSupported)
+ {
+ list.Add(TranscodeReason.AudioCodecNotSupported);
+ }
+
+ return list;
}
private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles)
@@ -393,6 +605,8 @@ namespace MediaBrowser.Model.Dlna
private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
{
+ List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
+
StreamInfo playlistItem = new StreamInfo
{
ItemId = options.ItemId,
@@ -428,7 +642,8 @@ namespace MediaBrowser.Model.Dlna
if (isEligibleForDirectPlay || isEligibleForDirectStream)
{
// See if it can be direct played
- PlayMethod? directPlay = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream);
+ var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream);
+ var directPlay = directPlayInfo.Item1;
if (directPlay != null)
{
@@ -445,6 +660,8 @@ namespace MediaBrowser.Model.Dlna
return playlistItem;
}
+
+ transcodeReasons.AddRange(directPlayInfo.Item2);
}
// Can't direct play, find the transcoding profile
@@ -521,8 +738,9 @@ namespace MediaBrowser.Model.Dlna
int? audioChannels = audioStream == null ? null : audioStream.Channels;
string audioProfile = audioStream == null ? null : audioStream.Profile;
int? inputAudioSampleRate = audioStream == null ? null : audioStream.SampleRate;
+ int? inputAudioBitDepth = audioStream == null ? null : audioStream.BitDepth;
- if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, audioProfile, isSecondaryAudio))
+ if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio))
{
LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
applyConditions = false;
@@ -618,6 +836,8 @@ namespace MediaBrowser.Model.Dlna
}
}
+ playlistItem.TranscodeReasons = transcodeReasons;
+
return playlistItem;
}
@@ -677,7 +897,7 @@ namespace MediaBrowser.Model.Dlna
return Math.Min(defaultBitrate, encoderAudioBitrateLimit);
}
- private PlayMethod? GetVideoDirectPlayProfile(VideoOptions options,
+ private Tuple<PlayMethod?, List<TranscodeReason>> GetVideoDirectPlayProfile(VideoOptions options,
MediaSourceInfo mediaSource,
MediaStream videoStream,
MediaStream audioStream,
@@ -688,11 +908,11 @@ namespace MediaBrowser.Model.Dlna
if (options.ForceDirectPlay)
{
- return PlayMethod.DirectPlay;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectPlay, new List<TranscodeReason>());
}
if (options.ForceDirectStream)
{
- return PlayMethod.DirectStream;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectStream, new List<TranscodeReason>());
}
if (videoStream == null)
@@ -701,7 +921,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path");
- return null;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownVideoStreamInfo });
}
// See if it can be direct played
@@ -721,7 +941,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path");
- return null;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, GetTranscodeReasonsFromDirectPlayProfile(mediaSource, videoStream, audioStream, profile.DirectPlayProfiles));
}
string container = mediaSource.Container;
@@ -757,6 +977,7 @@ namespace MediaBrowser.Model.Dlna
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;
TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
int? packetLength = videoStream == null ? null : videoStream.PacketLength;
@@ -784,7 +1005,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path");
- return null;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownVideoStreamInfo });
}
conditions = new List<ProfileCondition>();
@@ -819,7 +1040,12 @@ namespace MediaBrowser.Model.Dlna
{
LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource);
- return null;
+ var transcodeReason = GetTranscodeReasonForFailedCondition(i);
+ var transcodeReasons = transcodeReason.HasValue
+ ? new List<TranscodeReason> { transcodeReason.Value }
+ : new List<TranscodeReason> { };
+
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, transcodeReasons);
}
}
@@ -833,7 +1059,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path");
- return null;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownAudioStreamInfo });
}
conditions = new List<ProfileCondition>();
@@ -846,7 +1072,7 @@ namespace MediaBrowser.Model.Dlna
bool applyConditions = true;
foreach (ProfileCondition applyCondition in i.ApplyConditions)
{
- if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioSampleRate, audioProfile, isSecondaryAudio))
+ if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioSampleRate, audioBitDepth, audioProfile, isSecondaryAudio))
{
LogConditionFailure(profile, "VideoAudioCodecProfile", applyCondition, mediaSource);
applyConditions = false;
@@ -866,21 +1092,26 @@ namespace MediaBrowser.Model.Dlna
foreach (ProfileCondition i in conditions)
{
- if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioSampleRate, audioProfile, isSecondaryAudio))
+ if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioSampleRate, audioBitDepth, audioProfile, isSecondaryAudio))
{
LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource);
- return null;
+ var transcodeReason = GetTranscodeReasonForFailedCondition(i);
+ var transcodeReasons = transcodeReason.HasValue
+ ? new List<TranscodeReason> { transcodeReason.Value }
+ : new List<TranscodeReason> { };
+
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, transcodeReasons);
}
}
}
if (isEligibleForDirectStream && mediaSource.SupportsDirectStream)
{
- return PlayMethod.DirectStream;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectStream, new List<TranscodeReason>());
}
- return null;
+ return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.ContainerBitrateExceedsLimit });
}
private void LogConditionFailure(DeviceProfile profile, string type, ProfileCondition condition, MediaSourceInfo mediaSource)
@@ -1047,12 +1278,12 @@ namespace MediaBrowser.Model.Dlna
// Don't restrict by bitrate if coming from an external domain
if (item.IsRemote)
{
- return true;
+ return true;
}
if (!maxBitrate.HasValue)
{
- _logger.Info("Cannot "+ playMethod + " due to unknown supported bitrate");
+ _logger.Info("Cannot " + playMethod + " due to unknown supported bitrate");
return false;
}
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index ba5251e8c..9c8e8b030 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -21,6 +21,7 @@ namespace MediaBrowser.Model.Dlna
AudioCodecs = new string[] { };
VideoCodecs = new string[] { };
SubtitleCodecs = new string[] { };
+ TranscodeReasons = new List<TranscodeReason>();
}
public string ItemId { get; set; }
@@ -89,6 +90,7 @@ namespace MediaBrowser.Model.Dlna
public string PlaySessionId { get; set; }
public List<MediaSourceInfo> AllMediaSources { get; set; }
+ public List<TranscodeReason> TranscodeReasons { get; set; }
public string MediaSourceId
{
@@ -231,22 +233,11 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty));
list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty));
- var forceStartPosition = false;
long startPositionTicks = item.StartPositionTicks;
- //if (item.MediaSource.DateLiveStreamOpened.HasValue && startPositionTicks == 0)
- //{
- // var elapsed = DateTime.UtcNow - item.MediaSource.DateLiveStreamOpened.Value;
- // elapsed -= TimeSpan.FromSeconds(20);
- // if (elapsed.TotalSeconds >= 0)
- // {
- // startPositionTicks = elapsed.Ticks + startPositionTicks;
- // forceStartPosition = true;
- // }
- //}
var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls");
- if (isHls && !forceStartPosition)
+ if (isHls)
{
list.Add(new NameValuePair("StartTimeTicks", string.Empty));
}
@@ -310,6 +301,11 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString()));
}
+ if (isDlna || !item.IsDirectStream)
+ {
+ list.Add(new NameValuePair("TranscodeReasons", string.Join(",", item.TranscodeReasons.Distinct().Select(i => i.ToString()).ToArray())));
+ }
+
return list;
}
@@ -484,6 +480,18 @@ namespace MediaBrowser.Model.Dlna
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// </summary>
+ public int? TargetAudioBitDepth
+ {
+ get
+ {
+ MediaStream stream = TargetAudioStream;
+ return stream == null ? null : stream.BitDepth;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio sample rate that will be in the output stream
+ /// </summary>
public int? TargetVideoBitDepth
{
get