Browse Source

improve live stream pinging

Luke Pulverenti 10 years ago
parent
commit
623874ec8b

+ 37 - 7
MediaBrowser.Api/ApiEntryPoint.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Configuration;
@@ -40,6 +41,7 @@ namespace MediaBrowser.Api
 
         private readonly ISessionManager _sessionManager;
         private readonly IFileSystem _fileSystem;
+        private readonly IMediaSourceManager _mediaSourceManager;
 
         public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1);
 
@@ -49,12 +51,15 @@ namespace MediaBrowser.Api
         /// <param name="logger">The logger.</param>
         /// <param name="sessionManager">The session manager.</param>
         /// <param name="config">The configuration.</param>
-        public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem)
+        /// <param name="fileSystem">The file system.</param>
+        /// <param name="mediaSourceManager">The media source manager.</param>
+        public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager)
         {
             Logger = logger;
             _sessionManager = sessionManager;
             _config = config;
             _fileSystem = fileSystem;
+            _mediaSourceManager = mediaSourceManager;
 
             Instance = this;
         }
@@ -133,6 +138,7 @@ namespace MediaBrowser.Api
         /// </summary>
         /// <param name="path">The path.</param>
         /// <param name="playSessionId">The play session identifier.</param>
+        /// <param name="liveStreamId">The live stream identifier.</param>
         /// <param name="transcodingJobId">The transcoding job identifier.</param>
         /// <param name="type">The type.</param>
         /// <param name="process">The process.</param>
@@ -142,6 +148,7 @@ namespace MediaBrowser.Api
         /// <returns>TranscodingJob.</returns>
         public TranscodingJob OnTranscodeBeginning(string path,
             string playSessionId,
+            string liveStreamId,
             string transcodingJobId,
             TranscodingJobType type,
             Process process,
@@ -160,7 +167,8 @@ namespace MediaBrowser.Api
                     DeviceId = deviceId,
                     CancellationTokenSource = cancellationTokenSource,
                     Id = transcodingJobId,
-                    PlaySessionId = playSessionId
+                    PlaySessionId = playSessionId,
+                    LiveStreamId = liveStreamId
                 };
 
                 _activeTranscodingJobs.Add(job);
@@ -323,7 +331,7 @@ namespace MediaBrowser.Api
             }
         }
 
-        private void PingTimer(TranscodingJob job, bool isProgressCheckIn)
+        private async void PingTimer(TranscodingJob job, bool isProgressCheckIn)
         {
             if (job.HasExited)
             {
@@ -353,6 +361,18 @@ namespace MediaBrowser.Api
             {
                 job.ChangeKillTimerIfStarted();
             }
+
+            if (!string.IsNullOrWhiteSpace(job.LiveStreamId))
+            {
+                try
+                {
+                    await _mediaSourceManager.PingLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
+                }
+                catch (Exception ex)
+                {
+                    Logger.ErrorException("Error closing live stream", ex);
+                }
+            }
         }
 
         /// <summary>
@@ -365,9 +385,11 @@ namespace MediaBrowser.Api
 
             if (!job.HasExited && job.Type != TranscodingJobType.Progressive)
             {
-                if ((DateTime.UtcNow - job.LastPingDate).TotalMilliseconds < job.PingTimeout)
+                var timeSinceLastPing = (DateTime.UtcNow - job.LastPingDate).TotalMilliseconds;
+
+                if (timeSinceLastPing < job.PingTimeout)
                 {
-                    job.StartKillTimer(OnTranscodeKillTimerStopped);
+                    job.StartKillTimer(OnTranscodeKillTimerStopped, job.PingTimeout);
                     return;
                 }
             }
@@ -589,6 +611,11 @@ namespace MediaBrowser.Api
         /// <value>The play session identifier.</value>
         public string PlaySessionId { get; set; }
         /// <summary>
+        /// Gets or sets the live stream identifier.
+        /// </summary>
+        /// <value>The live stream identifier.</value>
+        public string LiveStreamId { get; set; }
+        /// <summary>
         /// Gets or sets the path.
         /// </summary>
         /// <value>The path.</value>
@@ -670,13 +697,16 @@ namespace MediaBrowser.Api
         }
 
         public void StartKillTimer(TimerCallback callback)
+        {
+            StartKillTimer(callback, PingTimeout);
+        }
+
+        public void StartKillTimer(TimerCallback callback, int intervalMs)
         {
             CheckHasExited();
 
             lock (_timerLock)
             {
-                var intervalMs = PingTimeout;
-
                 if (KillTimer == null)
                 {
                     Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);

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

@@ -1010,6 +1010,7 @@ namespace MediaBrowser.Api.Playback
 
             var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
                 state.Request.PlaySessionId,
+                state.MediaSource.LiveStreamId,
                 transcodingId,
                 TranscodingJobType,
                 process,

+ 2 - 0
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -309,6 +309,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="parentId">The parent identifier.</param>
         /// <param name="viewType">Type of the view.</param>
         /// <param name="sortName">Name of the sort.</param>
+        /// <param name="uniqueId">The unique identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;UserView&gt;.</returns>
         Task<UserView> GetNamedView(User user,
@@ -316,6 +317,7 @@ namespace MediaBrowser.Controller.Library
             string parentId,
             string viewType, 
             string sortName, 
+            string uniqueId,
             CancellationToken cancellationToken);
 
         /// <summary>

+ 1 - 1
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -49,7 +49,7 @@ namespace MediaBrowser.Model.Configuration
         /// </summary>
         /// <value><c>true</c> if [enable user specific user views]; otherwise, <c>false</c>.</value>
         public bool EnableUserSpecificUserViews { get; set; }
-
+        
         /// <summary>
         /// Gets or sets the value pointing to the file system where the ssl certiifcate is located..
         /// </summary>

+ 4 - 6
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -456,10 +456,8 @@ namespace MediaBrowser.Model.Dlna
                     playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
                 }
 
-                if (!playlistItem.AudioBitrate.HasValue)
-                {
-                    playlistItem.AudioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec);
-                }
+                int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec);
+                playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate);
 
                 int? maxBitrateSetting = options.GetMaxBitrate();
                 // Honor max rate
@@ -472,9 +470,9 @@ namespace MediaBrowser.Model.Dlna
                         videoBitrate -= playlistItem.AudioBitrate.Value;
                     }
 
+                    // Make sure the video bitrate is lower than bitrate settings but at least 64k
                     int currentValue = playlistItem.VideoBitrate ?? videoBitrate;
-
-                    playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue);
+                    playlistItem.VideoBitrate = Math.Max(Math.Min(videoBitrate, currentValue), 64000);
                 }
             }
 

+ 47 - 24
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -218,7 +218,7 @@ namespace MediaBrowser.Providers.MediaInfo
 
             await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
 
-            FetchEmbeddedInfo(video, mediaInfo);
+            FetchEmbeddedInfo(video, mediaInfo, options);
 
             video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
 
@@ -358,11 +358,13 @@ namespace MediaBrowser.Providers.MediaInfo
             return _blurayExaminer.GetDiscInfo(path);
         }
 
-        private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data)
+        private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
         {
+            var isFullRefresh = options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
+
             if (!video.LockedFields.Contains(MetadataFields.OfficialRating))
             {
-                if (!string.IsNullOrWhiteSpace(data.OfficialRating))
+                if (!string.IsNullOrWhiteSpace(data.OfficialRating) || isFullRefresh)
                 {
                     video.OfficialRating = data.OfficialRating;
                 }
@@ -370,54 +372,75 @@ namespace MediaBrowser.Providers.MediaInfo
 
             if (!video.LockedFields.Contains(MetadataFields.Cast))
             {
-                video.People.Clear();
-
-                foreach (var person in data.People)
+                if (video.People.Count == 0 || isFullRefresh)
                 {
-                    video.AddPerson(new PersonInfo
+                    video.People.Clear();
+
+                    foreach (var person in data.People)
                     {
-                        Name = person.Name,
-                        Type = person.Type,
-                        Role = person.Role
-                    });
+                        video.AddPerson(new PersonInfo
+                        {
+                            Name = person.Name,
+                            Type = person.Type,
+                            Role = person.Role
+                        });
+                    }
                 }
             }
 
             if (!video.LockedFields.Contains(MetadataFields.Genres))
             {
-                video.Genres.Clear();
-
-                foreach (var genre in data.Genres)
+                if (video.Genres.Count == 0 || isFullRefresh)
                 {
-                    video.AddGenre(genre);
+                    video.Genres.Clear();
+
+                    foreach (var genre in data.Genres)
+                    {
+                        video.AddGenre(genre);
+                    }
                 }
             }
 
             if (!video.LockedFields.Contains(MetadataFields.Studios))
             {
-                video.Studios.Clear();
-
-                foreach (var studio in data.Studios)
+                if (video.Studios.Count == 0 || isFullRefresh)
                 {
-                    video.AddStudio(studio);
+                    video.Studios.Clear();
+
+                    foreach (var studio in data.Studios)
+                    {
+                        video.AddStudio(studio);
+                    }
                 }
             }
 
             if (data.ProductionYear.HasValue)
             {
-                video.ProductionYear = data.ProductionYear;
+                if (!video.ProductionYear.HasValue || isFullRefresh)
+                {
+                    video.ProductionYear = data.ProductionYear;
+                }
             }
             if (data.PremiereDate.HasValue)
             {
-                video.PremiereDate = data.PremiereDate;
+                if (!video.PremiereDate.HasValue || isFullRefresh)
+                {
+                    video.PremiereDate = data.PremiereDate;
+                }
             }
             if (data.IndexNumber.HasValue)
             {
-                video.IndexNumber = data.IndexNumber;
+                if (!video.IndexNumber.HasValue || isFullRefresh)
+                {
+                    video.IndexNumber = data.IndexNumber;
+                }
             }
             if (data.ParentIndexNumber.HasValue)
             {
-                video.ParentIndexNumber = data.ParentIndexNumber;
+                if (!video.ParentIndexNumber.HasValue || isFullRefresh)
+                {
+                    video.ParentIndexNumber = data.ParentIndexNumber;
+                }
             }
 
             // If we don't have a ProductionYear try and get it from PremiereDate
@@ -428,7 +451,7 @@ namespace MediaBrowser.Providers.MediaInfo
 
             if (!video.LockedFields.Contains(MetadataFields.Overview))
             {
-                if (!string.IsNullOrWhiteSpace(data.Overview))
+                if (string.IsNullOrWhiteSpace(video.Overview) || isFullRefresh)
                 {
                     video.Overview = data.Overview;
                 }

+ 11 - 3
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1602,7 +1602,7 @@ namespace MediaBrowser.Server.Implementations.Library
         {
             if (ConfigurationManager.Configuration.EnableUserSpecificUserViews)
             {
-                return await GetNamedViewInternal(user, name, null, viewType, sortName, cancellationToken)
+                return await GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken)
                             .ConfigureAwait(false);
             }
 
@@ -1662,6 +1662,7 @@ namespace MediaBrowser.Server.Implementations.Library
             string parentId,
             string viewType,
             string sortName,
+            string uniqueId,
             CancellationToken cancellationToken)
         {
             if (string.IsNullOrWhiteSpace(parentId))
@@ -1669,7 +1670,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 throw new ArgumentNullException("parentId");
             }
 
-            return GetNamedViewInternal(user, name, parentId, viewType, sortName, cancellationToken);
+            return GetNamedViewInternal(user, name, parentId, viewType, sortName, uniqueId, cancellationToken);
         }
 
         private async Task<UserView> GetNamedViewInternal(User user,
@@ -1677,6 +1678,7 @@ namespace MediaBrowser.Server.Implementations.Library
             string parentId,
             string viewType,
             string sortName,
+            string uniqueId,
             CancellationToken cancellationToken)
         {
             if (string.IsNullOrWhiteSpace(name))
@@ -1684,7 +1686,13 @@ namespace MediaBrowser.Server.Implementations.Library
                 throw new ArgumentNullException("name");
             }
 
-            var id = GetNewItemId("37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty), typeof(UserView));
+            var idValues = "37_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty);
+            if (!string.IsNullOrWhiteSpace(uniqueId))
+            {
+                idValues += uniqueId;
+            }
+
+            var id = GetNewItemId(idValues, typeof(UserView));
 
             var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N"));
 

+ 21 - 16
MediaBrowser.Server.Implementations/Library/UserViewManager.cs

@@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || string.Equals(i.CollectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType))
@@ -105,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.Music, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.Music, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.CollectionType))
@@ -113,7 +113,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.Movies, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.Movies, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
@@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
@@ -129,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             parents = foldersWithViewTypes.Where(i => string.Equals(i.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
@@ -137,12 +137,12 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (parents.Count > 0)
             {
-                list.Add(await GetUserView(parents, CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(parents, list, CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false));
             }
 
             if (user.Configuration.DisplayFoldersView)
             {
-                list.Add(await GetUserView(new List<ICollectionFolder>(), CollectionType.Folders, "zz_" + CollectionType.Folders, user, cancellationToken).ConfigureAwait(false));
+                list.Add(await GetUserView(new List<ICollectionFolder>(), list, CollectionType.Folders, "zz_" + CollectionType.Folders, user, cancellationToken).ConfigureAwait(false));
             }
 
             if (query.IncludeExternalContent)
@@ -169,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId))
                 {
                     //list.Add(await _liveTvManager.GetInternalLiveTvFolder(query.UserId, cancellationToken).ConfigureAwait(false));
-                    list.Add(await GetUserView(new List<ICollectionFolder>(), CollectionType.LiveTv, string.Empty, user, cancellationToken).ConfigureAwait(false));
+                    list.Add(await GetUserView(new List<ICollectionFolder>(), list, CollectionType.LiveTv, string.Empty, user, cancellationToken).ConfigureAwait(false));
                 }
             }
 
@@ -190,7 +190,9 @@ namespace MediaBrowser.Server.Implementations.Library
 
         public Task<UserView> GetUserSubView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
         {
-            return _libraryManager.GetNamedView(user, name, parentId, type, sortName, cancellationToken);
+            var uniqueId = parentId + "subview" + type;
+
+            return _libraryManager.GetNamedView(user, name, parentId, type, sortName, uniqueId, cancellationToken);
         }
 
         public Task<UserView> GetUserSubView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
@@ -200,7 +202,7 @@ namespace MediaBrowser.Server.Implementations.Library
             return GetUserSubView(name, parentId, type, user, sortName, cancellationToken);
         }
 
-        public async Task<UserView> GetUserView(List<ICollectionFolder> parents, string viewType, string sortName, User user, CancellationToken cancellationToken)
+        public async Task<UserView> GetUserView(List<ICollectionFolder> parents, List<Folder> currentViews, string viewType, string sortName, User user, CancellationToken cancellationToken)
         {
             var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
 
@@ -215,7 +217,12 @@ namespace MediaBrowser.Server.Implementations.Library
 
                 var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase);
 
-                if (_config.Configuration.EnableUserSpecificUserViews || !enableRichView)
+                if (!enableRichView || currentViews.OfType<UserView>().Any(i => string.Equals(i.ViewType, viewType, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)))
+                {
+                    return await GetUserView(parentId, name, viewType, enableRichView, sortName, user, cancellationToken).ConfigureAwait(false);
+                }
+
+                if (_config.Configuration.EnableUserSpecificUserViews)
                 {
                     viewType = enableRichView ? viewType : null;
                     var view = await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
@@ -230,16 +237,14 @@ namespace MediaBrowser.Server.Implementations.Library
 
                 return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
             }
-            else
-            {
-                return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
-            }
+
+            return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
         }
 
         public Task<UserView> GetUserView(Guid parentId, string name, string viewType, bool enableRichView, string sortName, User user, CancellationToken cancellationToken)
         {
             viewType = enableRichView ? viewType : null;
-            return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, cancellationToken);
+            return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, null, cancellationToken);
         }
 
         public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)