Преглед изворни кода

add new streambuilder options

Luke Pulverenti пре 9 година
родитељ
комит
959c6a397c

+ 6 - 0
MediaBrowser.Model/Dlna/AudioOptions.cs

@@ -11,8 +11,14 @@ namespace MediaBrowser.Model.Dlna
         public AudioOptions()
         {
             Context = EncodingContext.Streaming;
+
+            EnableDirectPlay = true;
+            EnableDirectStream = true;
         }
 
+        public bool EnableDirectPlay { get; set; }
+        public bool EnableDirectStream { get; set; }
+
         public string ItemId { get; set; }
         public List<MediaSourceInfo> MediaSources { get; set; }
         public DeviceProfile Profile { get; set; }

+ 3 - 0
MediaBrowser.Model/Dlna/CodecProfile.cs

@@ -11,6 +11,8 @@ namespace MediaBrowser.Model.Dlna
        
         public ProfileCondition[] Conditions { get; set; }
 
+        public ProfileCondition[] ApplyConditions { get; set; }
+
         [XmlAttribute("codec")]
         public string Codec { get; set; }
 
@@ -20,6 +22,7 @@ namespace MediaBrowser.Model.Dlna
         public CodecProfile()
         {
             Conditions = new ProfileCondition[] {};
+            ApplyConditions = new ProfileCondition[] { };
         }
 
         public List<string> GetCodecs()

+ 133 - 25
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -131,6 +131,11 @@ namespace MediaBrowser.Model.Dlna
 
             List<PlayMethod> directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options);
 
+            ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+            int? inputAudioChannels = audioStream == null ? null : audioStream.Channels;
+            int? inputAudioBitrate = audioStream == null ? null : audioStream.BitDepth;
+
             if (directPlayMethods.Count > 0)
             {
                 string audioCodec = audioStream == null ? null : audioStream.Codec;
@@ -138,27 +143,36 @@ namespace MediaBrowser.Model.Dlna
                 // Make sure audio codec profiles are satisfied
                 if (!string.IsNullOrEmpty(audioCodec))
                 {
-                    ConditionProcessor conditionProcessor = new ConditionProcessor();
-
                     List<ProfileCondition> conditions = new List<ProfileCondition>();
                     foreach (CodecProfile i in options.Profile.CodecProfiles)
                     {
                         if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec, item.Container))
                         {
-                            foreach (ProfileCondition c in i.Conditions)
+                            bool applyConditions = true;
+                            foreach (ProfileCondition applyCondition in i.ApplyConditions)
                             {
-                                conditions.Add(c);
+                                if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate))
+                                {
+                                    LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
+                                    applyConditions = false;
+                                    break;
+                                }
+                            }
+
+                            if (applyConditions)
+                            {
+                                foreach (ProfileCondition c in i.Conditions)
+                                {
+                                    conditions.Add(c);
+                                }
                             }
                         }
                     }
 
-                    int? audioChannels = audioStream.Channels;
-                    int? audioBitrate = audioStream.BitRate;
-
                     bool all = true;
                     foreach (ProfileCondition c in conditions)
                     {
-                        if (!conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate))
+                        if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate))
                         {
                             LogConditionFailure(options.Profile, "AudioCodecProfile", c, item);
                             all = false;
@@ -241,9 +255,23 @@ namespace MediaBrowser.Model.Dlna
                 List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
                 foreach (CodecProfile i in audioCodecProfiles)
                 {
-                    foreach (ProfileCondition c in i.Conditions)
+                    bool applyConditions = true;
+                    foreach (ProfileCondition applyCondition in i.ApplyConditions)
                     {
-                        audioTranscodingConditions.Add(c);
+                        if (!conditionProcessor.IsAudioConditionSatisfied(applyCondition, inputAudioChannels, inputAudioBitrate))
+                        {
+                            LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
+                            applyConditions = false;
+                            break;
+                        }
+                    }
+
+                    if (applyConditions)
+                    {
+                        foreach (ProfileCondition c in i.Conditions)
+                        {
+                            audioTranscodingConditions.Add(c);
+                        }
                     }
                 }
 
@@ -294,7 +322,7 @@ 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()))
+                if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate()) && options.EnableDirectStream)
                 {
                     playMethods.Add(PlayMethod.DirectStream);
                 }
@@ -302,7 +330,7 @@ namespace MediaBrowser.Model.Dlna
                 // 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)))
+                    IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options)) && options.EnableDirectPlay)
                 {
                     playMethods.Add(PlayMethod.DirectPlay);
                 }
@@ -385,8 +413,8 @@ namespace MediaBrowser.Model.Dlna
             MediaStream videoStream = item.VideoStream;
 
             // TODO: This doesn't accout for situation of device being able to handle media bitrate, but wifi connection not fast enough
-            bool isEligibleForDirectPlay = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options, PlayMethod.DirectPlay);
-            bool isEligibleForDirectStream = IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options, PlayMethod.DirectStream);
+            bool isEligibleForDirectPlay = options.EnableDirectPlay && IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options, PlayMethod.DirectPlay);
+            bool isEligibleForDirectStream = options.EnableDirectStream && IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options, PlayMethod.DirectStream);
 
             _logger.Info("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
                 options.Profile.Name ?? "Unknown Profile",
@@ -463,17 +491,37 @@ namespace MediaBrowser.Model.Dlna
                 }
                 playlistItem.SubProtocol = transcodingProfile.Protocol;
                 playlistItem.AudioStreamIndex = audioStreamIndex;
+                ConditionProcessor conditionProcessor = new ConditionProcessor();
 
                 List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>();
                 foreach (CodecProfile i in options.Profile.CodecProfiles)
                 {
                     if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec, transcodingProfile.Container))
                     {
-                        foreach (ProfileCondition c in i.Conditions)
+                        bool applyConditions = true;
+                        foreach (ProfileCondition applyCondition in i.ApplyConditions)
                         {
-                            videoTranscodingConditions.Add(c);
+                            bool? isSecondaryAudio = audioStream == null ? null : item.IsSecondaryAudio(audioStream);
+                            int? inputAudioBitrate = audioStream == null ? null : audioStream.BitRate;
+                            int? audioChannels = audioStream == null ? null : audioStream.Channels;
+                            string audioProfile = audioStream == null ? null : audioStream.Profile;
+
+                            if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, audioProfile, isSecondaryAudio))
+                            {
+                                LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
+                                applyConditions = false;
+                                break;
+                            }
+                        }
+
+                        if (applyConditions)
+                        {
+                            foreach (ProfileCondition c in i.Conditions)
+                            {
+                                videoTranscodingConditions.Add(c);
+                            }
+                            break;
                         }
-                        break;
                     }
                 }
                 ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
@@ -483,11 +531,42 @@ namespace MediaBrowser.Model.Dlna
                 {
                     if (i.Type == CodecType.VideoAudio && i.ContainsCodec(playlistItem.TargetAudioCodec, transcodingProfile.Container))
                     {
-                        foreach (ProfileCondition c in i.Conditions)
+                        bool applyConditions = true;
+                        foreach (ProfileCondition applyCondition in i.ApplyConditions)
                         {
-                            audioTranscodingConditions.Add(c);
+                            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;
+                            float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
+                            bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic;
+                            string videoCodecTag = videoStream == null ? null : videoStream.CodecTag;
+
+                            TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : item.Timestamp;
+                            int? packetLength = videoStream == null ? null : videoStream.PacketLength;
+                            int? refFrames = videoStream == null ? null : videoStream.RefFrames;
+
+                            int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
+                            int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
+
+                            if (!conditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag))
+                            {
+                                LogConditionFailure(options.Profile, "VideoCodecProfile", applyCondition, item);
+                                applyConditions = false;
+                                break;
+                            }
+                        }
+
+                        if (applyConditions)
+                        {
+                            foreach (ProfileCondition c in i.Conditions)
+                            {
+                                audioTranscodingConditions.Add(c);
+                            }
+                            break;
                         }
-                        break;
                     }
                 }
                 ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
@@ -666,9 +745,23 @@ namespace MediaBrowser.Model.Dlna
             {
                 if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec, container))
                 {
-                    foreach (ProfileCondition c in i.Conditions)
+                    bool applyConditions = true;
+                    foreach (ProfileCondition applyCondition in i.ApplyConditions)
                     {
-                        conditions.Add(c);
+                        if (!conditionProcessor.IsVideoConditionSatisfied(applyCondition, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag))
+                        {
+                            LogConditionFailure(profile, "VideoCodecProfile", applyCondition, mediaSource);
+                            applyConditions = false;
+                            break;
+                        }
+                    }
+
+                    if (applyConditions)
+                    {
+                        foreach (ProfileCondition c in i.Conditions)
+                        {
+                            conditions.Add(c);
+                        }
                     }
                 }
             }
@@ -697,20 +790,35 @@ namespace MediaBrowser.Model.Dlna
                 }
 
                 conditions = new List<ProfileCondition>();
+                bool? isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream);
+
                 foreach (CodecProfile i in profile.CodecProfiles)
                 {
                     if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec, container))
                     {
-                        foreach (ProfileCondition c in i.Conditions)
+                        bool applyConditions = true;
+                        foreach (ProfileCondition applyCondition in i.ApplyConditions)
                         {
-                            conditions.Add(c);
+                            if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, audioBitrate, audioProfile, isSecondaryAudio))
+                            {
+                                LogConditionFailure(profile, "VideoAudioCodecProfile", applyCondition, mediaSource);
+                                applyConditions = false;
+                                break;
+                            }
+                        }
+
+                        if (applyConditions)
+                        {
+                            foreach (ProfileCondition c in i.Conditions)
+                            {
+                                conditions.Add(c);
+                            }
                         }
                     }
                 }
 
                 foreach (ProfileCondition i in conditions)
                 {
-                    bool? isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream);
                     if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile, isSecondaryAudio))
                     {
                         LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource);

+ 2 - 1
MediaBrowser.Providers/TV/DummySeasonProvider.cs

@@ -111,7 +111,8 @@ namespace MediaBrowser.Providers.TV
                 Name = seasonName,
                 IndexNumber = seasonNumber,
                 Id = _libraryManager.GetNewItemId((series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName), typeof(Season)),
-                IsVirtualItem = isVirtualItem
+                IsVirtualItem = isVirtualItem,
+                SeriesId = series.Id
             };
 
             season.SetParent(series);

+ 27 - 16
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -33,6 +33,7 @@ using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Controller.Channels;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Extensions;
@@ -353,10 +354,6 @@ namespace MediaBrowser.Server.Implementations.Library
 
         private void RegisterItem(Guid id, BaseItem item)
         {
-            if (item.SourceType != SourceType.Library)
-            {
-                return;
-            }
             if (item is IItemByName)
             {
                 if (!(item is MusicArtist))
@@ -364,14 +361,26 @@ namespace MediaBrowser.Server.Implementations.Library
                     return;
                 }
             }
-            if (item is Photo)
+
+            if (item.IsFolder)
             {
-                return;
+                if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel))
+                {
+                    if (item.SourceType != SourceType.Library)
+                    {
+                        return;
+                    }
+                }
             }
-            if (!(item is Folder))
+            else
             {
                 return;
+                if (item is Photo)
+                {
+                    return;
+                }
             }
+
             LibraryItemsCache.AddOrUpdate(id, item, delegate { return item; });
         }
 
@@ -782,19 +791,19 @@ namespace MediaBrowser.Server.Implementations.Library
 
         public BaseItem FindByPath(string path, bool? isFolder)
         {
+            // If this returns multiple items it could be tricky figuring out which one is correct. 
+            // In most cases, the newest one will be and the others obsolete but not yet cleaned up
+
             var query = new InternalItemsQuery
             {
                 Path = path,
-                IsFolder = isFolder
+                IsFolder = isFolder,
+                SortBy = new[] { ItemSortBy.DateCreated },
+                SortOrder = SortOrder.Descending,
+                Limit = 1
             };
 
-            // If this returns multiple items it could be tricky figuring out which one is correct. 
-            // In most cases, the newest one will be and the others obsolete but not yet cleaned up
-
-            return GetItemIds(query)
-                .Select(GetItemById)
-                .Where(i => i != null)
-                .OrderByDescending(i => i.DateCreated)
+            return GetItemList(query)
                 .FirstOrDefault();
         }
 
@@ -1258,6 +1267,8 @@ namespace MediaBrowser.Server.Implementations.Library
 
             item = RetrieveItem(id);
 
+            //_logger.Debug("GetitemById {0}", id);
+
             if (item != null)
             {
                 RegisterItem(item);
@@ -1508,7 +1519,7 @@ namespace MediaBrowser.Server.Implementations.Library
                         UserId = user.Id.ToString("N")
 
                     }, CancellationToken.None).Result;
-                    
+
                     return channelResult.Items;
                 }
 

+ 11 - 9
MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs

@@ -30,22 +30,24 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
                 return null;
             }
 
+            var season = parent as Season;
+            // Just in case the user decided to nest episodes. 
+            // Not officially supported but in some cases we can handle it.
+            if (season == null)
+            {
+                season = parent.GetParents().OfType<Season>().FirstOrDefault();
+            }
+
             // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
             // Also handle flat tv folders
-            if (string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+            if (season != null || 
+                string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || 
+                args.HasParent<Series>())
             {
                 var episode = ResolveVideo<Episode>(args, false);
 
                 if (episode != null)
                 {
-                    var season = parent as Season;
-                    // Just in case the user decided to nest episodes. 
-                    // Not officially supported but in some cases we can handle it.
-                    if (season == null)
-                    {
-                        season = parent.GetParents().OfType<Season>().FirstOrDefault();
-                    }
-
                     var series = parent as Series;
                     if (series == null)
                     {

+ 4 - 2
MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs

@@ -38,10 +38,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
             if (args.Parent is Series && args.IsDirectory)
             {
                 var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
-                
+                var series = ((Series)args.Parent);
+
                 var season = new Season
                 {
-                    IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber
+                    IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
+                    SeriesId = series.Id
                 };
                 
                 if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)