Browse Source

Merge pull request #2905 from MediaBrowser/dev

Dev
Luke 8 years ago
parent
commit
8586c9f6a7

+ 1 - 1
Emby.Server.Implementations/ApplicationHost.cs

@@ -2208,7 +2208,7 @@ namespace Emby.Server.Implementations
         {
             var updateLevel = SystemUpdateLevel;
             var cacheLength = updateLevel == PackageVersionClass.Release ?
-                TimeSpan.FromHours(4) :
+                TimeSpan.FromHours(12) :
                 TimeSpan.FromMinutes(5);
 
             var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser",

+ 1 - 1
Emby.Server.Implementations/Dto/DtoService.cs

@@ -571,7 +571,7 @@ namespace Emby.Server.Implementations.Dto
                 }
             }
 
-            if (!(item is LiveTvProgram) || fields.Contains(ItemFields.PlayAccess))
+            if (/*!(item is LiveTvProgram) ||*/ fields.Contains(ItemFields.PlayAccess))
             {
                 dto.PlayAccess = item.GetPlayAccess(user);
             }

+ 8 - 0
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -433,6 +433,14 @@ namespace Emby.Server.Implementations.Library
                             _fileSystem.DeleteFile(fileSystemInfo.FullName);
                         }
                     }
+                    catch (FileNotFoundException)
+                    {
+                        // may have already been deleted manually by user
+                    }
+                    catch (DirectoryNotFoundException)
+                    {
+                        // may have already been deleted manually by user
+                    }
                     catch (IOException)
                     {
                         if (isRequiredForDelete)

+ 19 - 17
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs

@@ -96,7 +96,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                             BufferContent = false,
 
                             // Increase a little bit
-                            TimeoutMs = 30000
+                            TimeoutMs = 30000,
+
+                            EnableHttpCompression = false
 
                         }, "GET").ConfigureAwait(false))
                         {
@@ -146,35 +148,35 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             });
         }
 
-        public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
-        {
-            return CopyFileTo(_tempFilePath, stream, cancellationToken);
-        }
-
-        protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken)
+        public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
         {
-            long startPosition = -20000;
-
-            _logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture));
-
             var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
             // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
 
-            using (var inputStream = (FileStream)GetInputStream(path, allowAsync))
+            using (var inputStream = (FileStream)GetInputStream(_tempFilePath, allowAsync))
             {
-                if (startPosition > 0)
-                {
-                    inputStream.Seek(-20000, SeekOrigin.End);
-                }
+                TrySeek(inputStream, -20000);
 
                 while (!cancellationToken.IsCancellationRequested)
                 {
-                    StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
+                    StreamHelper.CopyTo(inputStream, stream, 81920, cancellationToken);
 
                     //var position = fs.Position;
                     //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
                 }
             }
         }
+
+        private void TrySeek(FileStream stream, long offset)
+        {
+            try
+            {
+                stream.Seek(offset, SeekOrigin.End);
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error seeking stream", ex);
+            }
+        }
     }
 }

+ 16 - 16
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs

@@ -168,30 +168,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
            });
         }
 
-        public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
+        public async Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
         {
-            return CopyFileTo(_tempFilePath, stream, cancellationToken);
-        }
-
-        protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken)
-        {
-            long startPosition = -20000;
-
-            _logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture));
-
             var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
             // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
 
-            using (var inputStream = (FileStream)GetInputStream(path, allowAsync))
+            using (var inputStream = (FileStream)GetInputStream(_tempFilePath, allowAsync))
             {
-                if (startPosition > 0)
-                {
-                    inputStream.Seek(-20000, SeekOrigin.End);
-                }
+                TrySeek(inputStream, -20000);
 
                 while (!cancellationToken.IsCancellationRequested)
                 {
-                    StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
+                    StreamHelper.CopyTo(inputStream, stream, 81920, cancellationToken);
 
                     //var position = fs.Position;
                     //_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
@@ -199,6 +187,18 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             }
         }
 
+        private void TrySeek(FileStream stream, long offset)
+        {
+            try
+            {
+                stream.Seek(offset, SeekOrigin.End);
+            }
+            catch (Exception ex)
+            {
+                _logger.ErrorException("Error seeking stream", ex);
+            }
+        }
+
         private static int RtpHeaderBytes = 12;
         private void CopyTo(ISocket udpClient, Stream target, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
         {

+ 3 - 7
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -796,12 +796,13 @@ namespace MediaBrowser.Controller.MediaEncoding
 
             if (videoStream.IsInterlaced)
             {
-                if (request.DeInterlace)
+                if (state.DeInterlace(videoStream.Codec))
                 {
                     return false;
                 }
             }
 
+
             if (videoStream.IsAnamorphic ?? false)
             {
                 if (request.RequireNonAnamorphic)
@@ -1357,7 +1358,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                 filters.Add("hwupload");
             }
 
-            if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+            if (state.DeInterlace("h264") && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
             {
                 if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase))
                 {
@@ -1799,11 +1800,6 @@ namespace MediaBrowser.Controller.MediaEncoding
                     state.InternalSubtitleStreamOffset = mediaStreams.Where(i => i.Type == MediaStreamType.Subtitle && !i.IsExternal).ToList().IndexOf(state.SubtitleStream);
                 }
 
-                if (state.VideoStream != null && state.VideoStream.IsInterlaced)
-                {
-                    state.DeInterlace = true;
-                }
-
                 EnforceResolutionLimit(state);
 
                 NormalizeSubtitleEmbed(state);

+ 43 - 2
MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs

@@ -160,7 +160,26 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public int? OutputAudioBitrate;
         public int? OutputAudioChannels;
-        public bool DeInterlace { get; set; }
+
+        public bool DeInterlace(string videoCodec)
+        {
+            // Support general param
+            if (BaseRequest.DeInterlace)
+            {
+                return true;
+            }
+
+            if (!string.IsNullOrWhiteSpace(videoCodec))
+            {
+                if (string.Equals(BaseRequest.GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
         public bool IsVideoRequest { get; set; }
         public TranscodingJobType TranscodingType { get; set; }
 
@@ -435,6 +454,28 @@ namespace MediaBrowser.Controller.MediaEncoding
             }
         }
 
+        public string ActualOutputVideoCodec
+        {
+            get
+            {
+                var codec = OutputVideoCodec;
+
+                if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
+                {
+                    var stream = VideoStream;
+
+                    if (stream != null)
+                    {
+                        return stream.Codec;
+                    }
+
+                    return null;
+                }
+
+                return codec;
+            }
+        }
+
         public bool? IsTargetInterlaced
         {
             get
@@ -444,7 +485,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                     return VideoStream == null ? (bool?)null : VideoStream.IsInterlaced;
                 }
 
-                if (DeInterlace)
+                if (DeInterlace(ActualOutputVideoCodec))
                 {
                     return false;
                 }

+ 32 - 1
MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs

@@ -1,4 +1,6 @@
-using System.Globalization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Services;
 
@@ -224,12 +226,41 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public EncodingContext Context { get; set; }
 
+        public void SetOption(string qualifier, string name, string value)
+        {
+            SetOption(qualifier + "-" + name, value);
+        }
+
+        public Dictionary<string, string> StreamOptions { get; private set; }
+
+        public void SetOption(string name, string value)
+        {
+            StreamOptions[name] = value;
+        }
+
+        public string GetOption(string qualifier, string name)
+        {
+            return GetOption(qualifier + "-" + name);
+        }
+
+        public string GetOption(string name)
+        {
+            string value;
+            if (StreamOptions.TryGetValue(name, out value))
+            {
+                return value;
+            }
+
+            return null;
+        }
+
         public BaseEncodingJobOptions()
         {
             EnableAutoStreamCopy = true;
             AllowVideoStreamCopy = true;
             AllowAudioStreamCopy = true;
             Context = EncodingContext.Streaming;
+            StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         }
     }
 }

+ 75 - 11
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -406,7 +406,7 @@ namespace MediaBrowser.Model.Dlna
                     }
                 }
 
-                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
+                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions, null, false);
 
                 // Honor requested max channels
                 if (options.MaxAudioChannels.HasValue)
@@ -769,7 +769,7 @@ namespace MediaBrowser.Model.Dlna
                 playlistItem.AudioStreamIndex = audioStreamIndex;
                 ConditionProcessor conditionProcessor = new ConditionProcessor();
 
-                var videoTranscodingConditions = new List<ProfileCondition>();
+                var isFirstAppliedCodecProfile = true;
                 foreach (CodecProfile i in options.Profile.CodecProfiles)
                 {
                     if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec, transcodingProfile.Container))
@@ -786,7 +786,7 @@ namespace MediaBrowser.Model.Dlna
 
                             if (!conditionProcessor.IsVideoAudioConditionSatisfied(applyCondition, audioChannels, inputAudioBitrate, inputAudioSampleRate, inputAudioBitDepth, audioProfile, isSecondaryAudio))
                             {
-                                LogConditionFailure(options.Profile, "AudioCodecProfile", applyCondition, item);
+                                LogConditionFailure(options.Profile, "VideoAudioCodecProfile", applyCondition, item);
                                 applyConditions = false;
                                 break;
                             }
@@ -794,15 +794,14 @@ namespace MediaBrowser.Model.Dlna
 
                         if (applyConditions)
                         {
-                            foreach (ProfileCondition c in i.Conditions)
+                            foreach (var transcodingVideoCodec in ContainerProfile.SplitValue(transcodingProfile.VideoCodec))
                             {
-                                videoTranscodingConditions.Add(c);
+                                ApplyTranscodingConditions(playlistItem, i.Conditions, transcodingVideoCodec, !isFirstAppliedCodecProfile);
+                                isFirstAppliedCodecProfile = false;
                             }
-                            break;
                         }
                     }
                 }
-                ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
 
                 var audioTranscodingConditions = new List<ProfileCondition>();
                 foreach (CodecProfile i in options.Profile.CodecProfiles)
@@ -878,7 +877,7 @@ namespace MediaBrowser.Model.Dlna
                 }
 
                 // Do this after initial values are set to account for greater than/less than conditions
-                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
+                ApplyTranscodingConditions(playlistItem, audioTranscodingConditions, null, false);
             }
 
             playlistItem.TranscodeReasons = transcodeReasons;
@@ -1407,7 +1406,7 @@ namespace MediaBrowser.Model.Dlna
             }
         }
 
-        private void ApplyTranscodingConditions(StreamInfo item, IEnumerable<ProfileCondition> conditions)
+        private void ApplyTranscodingConditions(StreamInfo item, IEnumerable<ProfileCondition> conditions, string qualifier, bool qualifiedOnly)
         {
             foreach (ProfileCondition condition in conditions)
             {
@@ -1428,6 +1427,11 @@ namespace MediaBrowser.Model.Dlna
                 {
                     case ProfileConditionValue.AudioBitrate:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1448,6 +1452,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.AudioChannels:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1468,6 +1477,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.IsAvc:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             bool isAvc;
                             if (bool.TryParse(value, out isAvc))
                             {
@@ -1484,6 +1498,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.IsAnamorphic:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             bool isAnamorphic;
                             if (bool.TryParse(value, out isAnamorphic))
                             {
@@ -1500,16 +1519,21 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.IsInterlaced:
                         {
+                            if (string.IsNullOrWhiteSpace(qualifier))
+                            {
+                                continue;
+                            }
+
                             bool isInterlaced;
                             if (bool.TryParse(value, out isInterlaced))
                             {
                                 if (!isInterlaced && condition.Condition == ProfileConditionType.Equals)
                                 {
-                                    item.DeInterlace = true;
+                                    item.SetOption(qualifier, "deinterlace", "true");
                                 }
                                 else if (isInterlaced && condition.Condition == ProfileConditionType.NotEquals)
                                 {
-                                    item.DeInterlace = true;
+                                    item.SetOption(qualifier, "deinterlace", "true");
                                 }
                             }
                             break;
@@ -1527,6 +1551,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.RefFrames:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1547,6 +1576,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.VideoBitDepth:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1567,11 +1601,21 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.VideoProfile:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             item.VideoProfile = (value ?? string.Empty).Split('|')[0];
                             break;
                         }
                     case ProfileConditionValue.Height:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1592,6 +1636,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.VideoBitrate:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1612,6 +1661,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.VideoFramerate:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             float num;
                             if (float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1632,6 +1686,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.VideoLevel:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {
@@ -1652,6 +1711,11 @@ namespace MediaBrowser.Model.Dlna
                         }
                     case ProfileConditionValue.Width:
                         {
+                            if (qualifiedOnly)
+                            {
+                                continue;
+                            }
+
                             int num;
                             if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
                             {

+ 61 - 7
MediaBrowser.Model/Dlna/StreamInfo.cs

@@ -22,6 +22,33 @@ namespace MediaBrowser.Model.Dlna
             VideoCodecs = new string[] { };
             SubtitleCodecs = new string[] { };
             TranscodeReasons = new List<TranscodeReason>();
+            StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+        }
+
+        public void SetOption(string qualifier, string name, string value)
+        {
+            SetOption(qualifier + "-" + name, value);
+        }
+
+        public void SetOption(string name, string value)
+        {
+            StreamOptions[name] = value;
+        }
+
+        public string GetOption(string qualifier, string name)
+        {
+            return GetOption(qualifier + "-" + name);
+        }
+
+        public string GetOption(string name)
+        {
+            string value;
+            if (StreamOptions.TryGetValue(name, out value))
+            {
+                return value;
+            }
+
+            return null;
         }
 
         public string ItemId { get; set; }
@@ -44,7 +71,6 @@ namespace MediaBrowser.Model.Dlna
         public bool BreakOnNonKeyFrames { get; set; }
 
         public bool RequireAvc { get; set; }
-        public bool DeInterlace { get; set; }
         public bool RequireNonAnamorphic { get; set; }
         public bool CopyTimestamps { get; set; }
         public bool EnableSubtitlesInManifest { get; set; }
@@ -92,6 +118,8 @@ namespace MediaBrowser.Model.Dlna
         public List<MediaSourceInfo> AllMediaSources { get; set; }
         public List<TranscodeReason> TranscodeReasons { get; set; }
 
+        public Dictionary<string, string> StreamOptions { get; private set; }
+
         public string MediaSourceId
         {
             get
@@ -282,7 +310,16 @@ namespace MediaBrowser.Model.Dlna
             list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty));
 
             list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString().ToLower()));
-            list.Add(new NameValuePair("DeInterlace", item.DeInterlace.ToString().ToLower()));
+
+            if (isDlna)
+            {
+                // hack alert
+                // dlna needs to be update to support the qualified params
+                var deinterlace = string.Equals(item.GetOption("h264", "deinterlace"), "true", StringComparison.OrdinalIgnoreCase) ||
+                                  string.Equals(item.GetOption("mpeg2video", "deinterlace"), "true", StringComparison.OrdinalIgnoreCase);
+
+                list.Add(new NameValuePair("DeInterlace", deinterlace.ToString().ToLower()));
+            }
 
             if (!isDlna && isHls)
             {
@@ -306,6 +343,19 @@ namespace MediaBrowser.Model.Dlna
                 list.Add(new NameValuePair("TranscodeReasons", string.Join(",", item.TranscodeReasons.Distinct().Select(i => i.ToString()).ToArray())));
             }
 
+            if (!isDlna)
+            {
+                foreach (var pair in item.StreamOptions)
+                {
+                    if (string.IsNullOrWhiteSpace(pair.Value))
+                    {
+                        continue;
+                    }
+
+                    list.Add(new NameValuePair(pair.Key, pair.Value));
+                }
+            }
+
             return list;
         }
 
@@ -675,10 +725,10 @@ namespace MediaBrowser.Model.Dlna
                 return VideoCodecs.Length == 0 ? null : VideoCodecs[0];
             }
         }
-        
+
         /// <summary>
-             /// Predicts the audio channels that will be in the output stream
-             /// </summary>
+        /// Predicts the audio channels that will be in the output stream
+        /// </summary>
         public long? TargetSize
         {
             get
@@ -763,9 +813,13 @@ namespace MediaBrowser.Model.Dlna
                     return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced;
                 }
 
-                if (DeInterlace)
+                var videoCodec = TargetVideoCodec;
+                if (!string.IsNullOrWhiteSpace(videoCodec))
                 {
-                    return false;
+                    if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
+                    {
+                        return false;
+                    }
                 }
 
                 return TargetVideoStream == null ? (bool?)null : TargetVideoStream.IsInterlaced;

+ 1 - 1
SharedVersion.cs

@@ -1,3 +1,3 @@
 using System.Reflection;
 
-[assembly: AssemblyVersion("3.2.31")]
+[assembly: AssemblyVersion("3.2.32.1")]