Bläddra i källkod

capture more transcoding info

Luke Pulverenti 8 år sedan
förälder
incheckning
a107ff0369

+ 2 - 1
MediaBrowser.Api/ApiEntryPoint.cs

@@ -265,7 +265,8 @@ namespace MediaBrowser.Api
                     Height = state.OutputHeight,
                     AudioChannels = state.OutputAudioChannels,
                     IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase),
-                    IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)
+                    IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase),
+                    TranscodeReasons = state.TranscodeReasons
                 });
             }
         }

+ 4 - 0
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -583,6 +583,10 @@ namespace MediaBrowser.Api.Playback
                         videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
                     }
                 }
+                else if (i == 33)
+                {
+                    request.TranscodeReasons = val;
+                }
             }
         }
 

+ 5 - 0
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -541,6 +541,11 @@ namespace MediaBrowser.Api.Playback.Hls
             {
                 queryString += "&SegmentContainer=" + state.Request.SegmentContainer;
             }
+            // from universal audio service
+            if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) && queryString.IndexOf("TranscodeReasons=", StringComparison.OrdinalIgnoreCase) == -1)
+            {
+                queryString += "&TranscodeReasons=" + state.Request.TranscodeReasons;
+            }
 
             // Main stream
             var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8";

+ 2 - 0
MediaBrowser.Api/Playback/MediaInfoService.cs

@@ -513,6 +513,8 @@ namespace MediaBrowser.Api.Playback
             var profiles = info.GetSubtitleProfiles(false, "-", accessToken);
             mediaSource.DefaultSubtitleStreamIndex = info.SubtitleStreamIndex;
 
+            mediaSource.TranscodeReasons = info.TranscodeReasons;
+
             foreach (var profile in profiles)
             {
                 foreach (var stream in mediaSource.MediaStreams)

+ 5 - 2
MediaBrowser.Api/Playback/UniversalAudioService.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Globalization;
+using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Api.Playback.Hls;
 using MediaBrowser.Api.Playback.Progressive;
@@ -265,7 +266,8 @@ namespace MediaBrowser.Api.Playback
                     Static = isStatic,
                     SegmentContainer = request.TranscodingContainer,
                     AudioSampleRate = request.MaxAudioSampleRate,
-                    BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames
+                    BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames,
+                    TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray())
                 };
 
                 if (isHeadRequest)
@@ -307,7 +309,8 @@ namespace MediaBrowser.Api.Playback
                     PlaySessionId = playbackInfoResult.PlaySessionId,
                     StartTimeTicks = request.StartTimeTicks,
                     Static = isStatic,
-                    AudioSampleRate = request.MaxAudioSampleRate
+                    AudioSampleRate = request.MaxAudioSampleRate,
+                    TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray())
                 };
 
                 if (isHeadRequest)

+ 4 - 4
MediaBrowser.Controller/Entities/Folder.cs

@@ -487,7 +487,7 @@ namespace MediaBrowser.Controller.Entities
                     var folder = this;
                     innerProgress.RegisterAction(p =>
                     {
-                        double newPct = .70 * p + 10;
+                        double newPct = .80 * p + 10;
                         progress.Report(newPct);
                         ProviderManager.OnRefreshProgress(folder, newPct);
                     });
@@ -498,11 +498,11 @@ namespace MediaBrowser.Controller.Entities
 
             if (refreshChildMetadata)
             {
-                progress.Report(80);
+                progress.Report(90);
 
                 if (recursive)
                 {
-                    ProviderManager.OnRefreshProgress(this, 80);
+                    ProviderManager.OnRefreshProgress(this, 90);
                 }
 
                 var container = this as IMetadataContainer;
@@ -512,7 +512,7 @@ namespace MediaBrowser.Controller.Entities
                     var folder = this;
                     innerProgress.RegisterAction(p =>
                     {
-                        double newPct = .20 * p + 80;
+                        double newPct = .10 * p + 90;
                         progress.Report(newPct);
                         if (recursive)
                         {

+ 21 - 1
MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Globalization;
+using System.Linq;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Dto;
@@ -9,6 +10,7 @@ using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.MediaInfo;
 using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Session;
 
 namespace MediaBrowser.Controller.MediaEncoding
 {
@@ -40,6 +42,24 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public bool ReadInputAtNativeFramerate { get; set; }
 
+        private List<TranscodeReason> _transcodeReasons = null;
+        public List<TranscodeReason> TranscodeReasons
+        {
+            get
+            {
+                if (_transcodeReasons == null)
+                {
+                    _transcodeReasons = (BaseRequest.TranscodeReasons ?? string.Empty)
+                        .Split(',')
+                        .Where(i => !string.IsNullOrWhiteSpace(i))
+                        .Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
+                        .ToList();
+                }
+
+                return _transcodeReasons;
+            }
+        }
+
         public bool IgnoreInputDts
         {
             get
@@ -251,7 +271,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                     {
                         return AudioStream.SampleRate;
                     }
-                } 
+                }
 
                 else if (BaseRequest.AudioSampleRate.HasValue)
                 {

+ 2 - 0
MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs

@@ -204,6 +204,8 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public string SubtitleCodec { get; set; }
 
+        public string TranscodeReasons { get; set; }
+
         /// <summary>
         /// Gets or sets the index of the audio stream.
         /// </summary>

+ 0 - 1
MediaBrowser.Model/Configuration/UserConfiguration.cs

@@ -55,7 +55,6 @@ namespace MediaBrowser.Model.Configuration
 
             HidePlayedInLatest = true;
             PlayDefaultAudioTrack = true;
-            DisplayMissingEpisodes = true;
 
             LatestItemsExcludes = new string[] { };
             OrderedViews = new string[] { };

+ 0 - 1
MediaBrowser.Model/Dlna/ProfileCondition.cs

@@ -1,5 +1,4 @@
 using System.Xml.Serialization;
-using MediaBrowser.Model.Dlna;
 
 namespace MediaBrowser.Model.Dlna
 {

+ 248 - 23
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -105,8 +105,99 @@ 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.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,7 +224,10 @@ 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();
 
@@ -180,6 +274,11 @@ namespace MediaBrowser.Model.Dlna
                         if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate))
                         {
                             LogConditionFailure(options.Profile, "AudioCodecProfile", c, item);
+                            var transcodeReason = GetTranscodeReasonForFailedCondition(c);
+                            if (transcodeReason.HasValue)
+                            {
+                                transcodeReasons.Add(transcodeReason.Value);
+                            }
                             all = false;
                             break;
                         }
@@ -292,9 +391,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 +407,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 +426,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.VideoCodecNotSupported);
+            }
+
+            return list;
         }
 
         private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles)
@@ -393,6 +601,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 +638,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 +656,8 @@ namespace MediaBrowser.Model.Dlna
 
                     return playlistItem;
                 }
+
+                transcodeReasons.AddRange(directPlayInfo.Item2);
             }
 
             // Can't direct play, find the transcoding profile
@@ -618,6 +831,8 @@ namespace MediaBrowser.Model.Dlna
                 }
             }
 
+            playlistItem.TranscodeReasons = transcodeReasons;
+
             return playlistItem;
         }
 
@@ -677,7 +892,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 +903,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 +916,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 +936,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;
@@ -784,7 +999,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 +1034,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 +1053,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>();
@@ -870,17 +1090,22 @@ namespace MediaBrowser.Model.Dlna
                     {
                         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 +1272,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;
             }
 

+ 8 - 12
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;
         }
 

+ 4 - 0
MediaBrowser.Model/Dto/MediaSourceInfo.cs

@@ -4,6 +4,7 @@ using MediaBrowser.Model.MediaInfo;
 using System.Collections.Generic;
 using System.Linq;
 using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Session;
 
 namespace MediaBrowser.Model.Dto
 {
@@ -110,6 +111,9 @@ namespace MediaBrowser.Model.Dto
             }
         }
 
+        [IgnoreDataMember]
+        public List<TranscodeReason> TranscodeReasons { get; set; }
+
         public int? DefaultAudioStreamIndex { get; set; }
         public int? DefaultSubtitleStreamIndex { get; set; }
 

+ 33 - 0
MediaBrowser.Model/Session/TranscodingInfo.cs

@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
 namespace MediaBrowser.Model.Session
 {
     public class TranscodingInfo
@@ -15,5 +17,36 @@ namespace MediaBrowser.Model.Session
         public int? Width { get; set; }
         public int? Height { get; set; }
         public int? AudioChannels { get; set; }
+
+        public List<TranscodeReason> TranscodeReasons { get; set; }
+
+        public TranscodingInfo()
+        {
+            TranscodeReasons = new List<TranscodeReason>();
+        }
+    }
+
+    public enum TranscodeReason
+    {
+        ContainerNotSupported = 0,
+        VideoCodecNotSupported = 1,
+        AudioCodecNotSupported = 2,
+        ContainerBitrateExceedsLimit = 3,
+        AudioBitrateNotSupported = 4,
+        AudioChannelsNotSupported = 5,
+        VideoResolutionNotSupported = 6,
+        UnknownVideoStreamInfo = 7,
+        UnknownAudioStreamInfo = 8,
+        AudioProfileNotSupported = 9,
+        AudioSampleRateNotSupported = 10,
+        AnamorphicVideoNotSupported = 11,
+        InterlacedVideoNotSupported = 12,
+        SecondaryAudioNotSupported = 13,
+        RefFramesNotSupported = 14,
+        VideoBitDepthNotSupported = 15,
+        VideoBitrateNotSupported = 16,
+        VideoFramerateNotSupported = 17,
+        VideoLevelNotSupported = 18,
+        VideoProfileNotSupported = 19
     }
 }