From 26094af11522dfc100d709dcd9296805ba1e3fc7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 13 Apr 2015 12:21:10 -0400 Subject: [PATCH] update live stream termination --- MediaBrowser.Api/ApiEntryPoint.cs | 2 +- .../Playback/Hls/BaseHlsService.cs | 16 +++++- .../Playback/Hls/VideoHlsService.cs | 2 - .../EntryPoints/ExternalPortForwarding.cs | 55 +++++++++++++++---- 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index fd7ad2cf56..ba51f4f8c5 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -340,7 +340,7 @@ namespace MediaBrowser.Api // We can really reduce the timeout for apps that are using the newer api if (!string.IsNullOrWhiteSpace(job.PlaySessionId) && job.Type != TranscodingJobType.Progressive) { - timerDuration = 35000; + timerDuration = 20000; } if (job.KillTimer == null) diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 701516b48c..919fe07733 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -85,6 +85,7 @@ namespace MediaBrowser.Api.Playback.Hls state.Request.StartTimeTicks = null; } + TranscodingJob job = null; var playlist = state.OutputFilePath; if (!File.Exists(playlist)) @@ -97,7 +98,7 @@ namespace MediaBrowser.Api.Playback.Hls // If the playlist doesn't already exist, startup ffmpeg try { - await StartFfMpeg(state, playlist, cancellationTokenSource).ConfigureAwait(false); + job = await StartFfMpeg(state, playlist, cancellationTokenSource).ConfigureAwait(false); } catch { @@ -116,6 +117,12 @@ namespace MediaBrowser.Api.Playback.Hls if (isLive) { + job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType); + + if (job != null) + { + ApiEntryPoint.Instance.OnTranscodeEndRequest(job); + } return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } @@ -134,6 +141,13 @@ namespace MediaBrowser.Api.Playback.Hls var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate); + job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType); + + if (job != null) + { + ApiEntryPoint.Instance.OnTranscodeEndRequest(job); + } + return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index b1964f4aef..8e2854c5e8 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -3,12 +3,10 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; using ServiceStack; using System; -using System.IO; namespace MediaBrowser.Api.Playback.Hls { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 5c69db3e10..966e0a3e48 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller; +using System.Linq; +using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; @@ -47,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints void _config_ConfigurationUpdated(object sender, EventArgs e) { _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - + if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { if (_isStarted) @@ -88,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints NatUtility.UnhandledException += NatUtility_UnhandledException; NatUtility.StartDiscovery(); - _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); _lastConfigIdentifier = GetConfigIdentifier(); @@ -119,7 +120,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints CreateRules(device); } - catch (Exception) + catch (Exception ex) { // I think it could be a good idea to log the exception because // you are using permanent portmapping here (never expire) and that means that next time @@ -128,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable // and those errors (upnp errors) could be useful for diagnosting. - //_logger.ErrorException("Error creating port forwarding rules", ex); + _logger.ErrorException("Error creating port forwarding rules", ex); } } @@ -138,25 +139,55 @@ namespace MediaBrowser.Server.Implementations.EntryPoints // On some systems the device discovered event seems to fire repeatedly // This check will help ensure we're not trying to port map the same device over and over + List currentMappings = null; + + try + { + currentMappings = device.GetAllMappings().ToList(); + } + catch (NotSupportedException) + { + } + var address = device.LocalAddress.ToString(); if (!_createdRules.Contains(address)) { _createdRules.Add(address); - CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + CreatePortMap(device, currentMappings, _appHost.HttpPort, _config.Configuration.PublicPort); + CreatePortMap(device, currentMappings, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); } } - private void CreatePortMap(INatDevice device, int privatePort, int publicPort) + private void CreatePortMap(INatDevice device, List currentMappings, int privatePort, int publicPort) { - _logger.Debug("Creating port map on port {0}", privatePort); + var hasMapping = false; + + if (currentMappings != null) + { + hasMapping = currentMappings.Any(i => i.PublicPort == publicPort && i.PrivatePort == privatePort); + } + else + { + try + { + var mapping = device.GetSpecificMapping(Protocol.Tcp, publicPort); + hasMapping = mapping != null; + } + catch (NotSupportedException) + { + } + } - device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) + if (!hasMapping) { - Description = _appHost.Name - }); + _logger.Debug("Creating port map on port {0}", privatePort); + device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) + { + Description = _appHost.Name + }); + } } // As I said before, this method will be never invoked. You can remove it.