From 525f7804532bb0d5a1dc38668fbcf511acc2877c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Jun 2016 00:23:52 -0400 Subject: add startup error handling --- .../Encoder/EncoderValidator.cs | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs new file mode 100644 index 000000000..99581332d --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public class EncoderValidator + { + private readonly ILogger _logger; + + public EncoderValidator(ILogger logger) + { + _logger = logger; + } + + public Tuple, List> Validate(string encoderPath) + { + _logger.Info("Validating media encoder at {0}", encoderPath); + + var decoders = GetDecoders(encoderPath); + var encoders = GetEncoders(encoderPath); + + _logger.Info("Encoder validation complete"); + + return new Tuple, List>(decoders, encoders); + } + + private List GetDecoders(string ffmpegPath) + { + string output = string.Empty; + try + { + output = GetFFMpegOutput(ffmpegPath, "-decoders"); + } + catch + { + } + //_logger.Debug("ffmpeg decoder query result: {0}", output ?? string.Empty); + + var found = new List(); + var required = new[] + { + "h264_qsv", + "mpeg2_qsv", + "vc1_qsv" + }; + + foreach (var codec in required) + { + var srch = " " + codec + " "; + + if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1) + { + _logger.Warn("ffmpeg is missing decoder " + codec); + } + else + { + found.Add(codec); + } + } + + return found; + } + + private List GetEncoders(string ffmpegPath) + { + string output = null; + try + { + output = GetFFMpegOutput(ffmpegPath, "-encoders"); + } + catch + { + } + //_logger.Debug("ffmpeg encoder query result: {0}", output ?? string.Empty); + + var found = new List(); + var required = new[] + { + "libx264", + "libx265", + "mpeg4", + "msmpeg4", + //"libvpx", + //"libvpx-vp9", + "aac", + "libmp3lame", + "libopus", + //"libvorbis", + "srt" + }; + + foreach (var codec in required) + { + var srch = " " + codec + " "; + + if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1) + { + _logger.Warn("ffmpeg is missing encoder " + codec); + } + else + { + found.Add(codec); + } + } + + return found; + } + + private string GetFFMpegOutput(string path, string arguments) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + FileName = path, + Arguments = arguments, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + RedirectStandardOutput = true, + RedirectStandardError = true + } + }; + + using (process) + { + process.Start(); + + try + { + process.BeginErrorReadLine(); + + using (var reader = new StreamReader(process.StandardOutput.BaseStream)) + { + return reader.ReadToEnd(); + } + } + catch + { + // Hate having to do this + try + { + process.Kill(); + } + catch (Exception ex1) + { + _logger.ErrorException("Error killing ffmpeg", ex1); + } + + throw; + } + } + } + } +} -- cgit v1.2.3 From 9a012e458cd12ca7b9630ce7f3074318db9deee8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Jun 2016 00:41:15 -0400 Subject: update validation --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 99581332d..6059108c8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -134,13 +134,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { process.BeginErrorReadLine(); - using (var reader = new StreamReader(process.StandardOutput.BaseStream)) - { - return reader.ReadToEnd(); - } + return process.StandardOutput.ReadToEnd(); } catch { + _logger.Info("Killing process {0} {1}", path, arguments); + // Hate having to do this try { -- cgit v1.2.3 From 52d8ddb050f89a9e7130b48918f60655c644580b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Jun 2016 14:59:18 -0400 Subject: support h264_omx --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 46 +++++++++++++--------- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 24 +++++++---- .../Encoder/EncoderValidator.cs | 32 ++++++--------- .../Encoder/EncodingJobFactory.cs | 18 ++++++--- 4 files changed, 69 insertions(+), 51 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4f1a29a4d..01d959d70 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -286,11 +286,19 @@ namespace MediaBrowser.Api.Playback protected string GetH264Encoder(StreamState state) { - if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { - return "h264_qsv"; + } + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "libnvenc", StringComparison.OrdinalIgnoreCase)) + { + return "libnvenc"; + } + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "h264_omx", StringComparison.OrdinalIgnoreCase)) + { + return "h264_omx"; } return "libx264"; @@ -395,15 +403,18 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) { - param += " -profile:v " + state.VideoRequest.Profile; + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + { + // not supported by h264_omx + param += " -profile:v " + state.VideoRequest.Profile; + } } if (!string.IsNullOrEmpty(state.VideoRequest.Level)) { - var h264Encoder = GetH264Encoder(state); - // h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (String.Equals(h264Encoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || String.Equals(h264Encoder, "libnvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) { switch (state.VideoRequest.Level) { @@ -438,16 +449,21 @@ namespace MediaBrowser.Api.Playback param += " -level " + state.VideoRequest.Level; break; } - - return param; } - else + else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) { param += " -level " + state.VideoRequest.Level; } } - return "-pix_fmt yuv420p " + param; + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + { + param = "-pix_fmt yuv420p " + param; + } + + return param; } protected string GetAudioFilterParam(StreamState state, bool isHls) @@ -563,14 +579,6 @@ namespace MediaBrowser.Api.Playback filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam)); } - if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) - { - if (filters.Count > 1) - { - //filters[filters.Count - 1] += ":flags=fast_bilinear"; - } - } - var output = string.Empty; if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode) @@ -1650,7 +1658,7 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrWhiteSpace(request.AudioCodec)) { state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i)) + state.Request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i)) ?? state.SupportedAudioCodecs.FirstOrDefault(); } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 22f739801..77bd50b9b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -377,7 +377,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (MediaEncoder.SupportsDecoder("h264_qsv")) { // Seeing stalls and failures with decoding. Not worth it compared to encoding. - //return "-c:v h264_qsv "; + return "-c:v h264_qsv "; } break; case "mpeg2video": @@ -672,17 +672,20 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.Options.Profile)) { - param += " -profile:v " + state.Options.Profile; + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + { + // not supported by h264_omx + param += " -profile:v " + state.Options.Profile; + } } var levelString = state.Options.Level.HasValue ? state.Options.Level.Value.ToString(CultureInfo.InvariantCulture) : null; if (!string.IsNullOrEmpty(levelString)) { - var h264Encoder = EncodingJobFactory.GetH264Encoder(state, GetEncodingOptions()); - // h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (String.Equals(h264Encoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || String.Equals(h264Encoder, "libnvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) { switch (levelString) { @@ -718,13 +721,20 @@ namespace MediaBrowser.MediaEncoding.Encoder break; } } - else + else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) { param += " -level " + levelString; } } - return "-pix_fmt yuv420p " + param; + if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + { + param = "-pix_fmt yuv420p " + param; + } + + return param; } protected string GetVideoBitrateParam(EncodingJob state, string videoCodec) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 6059108c8..133cc8d70 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -27,17 +27,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return new Tuple, List>(decoders, encoders); } - private List GetDecoders(string ffmpegPath) + private List GetDecoders(string encoderAppPath) { string output = string.Empty; try { - output = GetFFMpegOutput(ffmpegPath, "-decoders"); + output = GetProcessOutput(encoderAppPath, "-decoders"); } catch { } - //_logger.Debug("ffmpeg decoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -51,12 +50,9 @@ namespace MediaBrowser.MediaEncoding.Encoder { var srch = " " + codec + " "; - if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1) - { - _logger.Warn("ffmpeg is missing decoder " + codec); - } - else + if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) != -1) { + _logger.Info("Decoder available: " + codec); found.Add(codec); } } @@ -64,17 +60,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } - private List GetEncoders(string ffmpegPath) + private List GetEncoders(string encoderAppPath) { string output = null; try { - output = GetFFMpegOutput(ffmpegPath, "-encoders"); + output = GetProcessOutput(encoderAppPath, "-encoders"); } catch { } - //_logger.Debug("ffmpeg encoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -89,19 +84,18 @@ namespace MediaBrowser.MediaEncoding.Encoder "libmp3lame", "libopus", //"libvorbis", - "srt" + "srt", + "libnvenc", + "h264_qsv" }; foreach (var codec in required) { var srch = " " + codec + " "; - if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1) - { - _logger.Warn("ffmpeg is missing encoder " + codec); - } - else + if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) != -1) { + _logger.Info("Encoder available: " + codec); found.Add(codec); } } @@ -109,7 +103,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return found; } - private string GetFFMpegOutput(string path, string arguments) + private string GetProcessOutput(string path, string arguments) { var process = new Process { @@ -147,7 +141,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch (Exception ex1) { - _logger.ErrorException("Error killing ffmpeg", ex1); + _logger.ErrorException("Error killing process", ex1); } throw; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 7fe7facdf..177009306 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -556,13 +556,19 @@ namespace MediaBrowser.MediaEncoding.Encoder internal static string GetH264Encoder(EncodingJob state, EncodingOptions options) { - if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(options.HardwareAccelerationType, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { - // It's currently failing on live tv - if (state.RunTimeTicks.HasValue) - { - return "h264_qsv"; - } + return "h264_qsv"; + } + + if (string.Equals(options.HardwareAccelerationType, "libnvenc", StringComparison.OrdinalIgnoreCase)) + { + return "libnvenc"; + } + if (string.Equals(options.HardwareAccelerationType, "h264_omx", StringComparison.OrdinalIgnoreCase)) + { + return "h264_omx"; } return "libx264"; -- cgit v1.2.3 From ffd3101ac63d082e8086311b98db5b2ef3971c12 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 30 Jun 2016 17:04:26 -0400 Subject: Fixes for nvenc support marked as experimental, since more testing should be done on options --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 14 +++++++------- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 12 ++++++------ MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 01d959d70..e3eb1e4ba 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -292,9 +292,9 @@ namespace MediaBrowser.Api.Playback return "h264_qsv"; } - if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "libnvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - return "libnvenc"; + return "h264_nvenc"; } if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "h264_omx", StringComparison.OrdinalIgnoreCase)) { @@ -338,8 +338,8 @@ namespace MediaBrowser.Api.Playback } - // h264 (libnvenc) - else if (string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + // h264 (h264_nvenc) + else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param = "-preset high-performance"; } @@ -412,9 +412,9 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Level)) { - // h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { switch (state.VideoRequest.Level) { @@ -458,7 +458,7 @@ namespace MediaBrowser.Api.Playback if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 77bd50b9b..9eb796360 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -607,10 +607,10 @@ namespace MediaBrowser.MediaEncoding.Encoder } - // h264 (libnvenc) - else if (string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + // h264 (h264_nvenc) + else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { - param = "-preset high-performance"; + param = "-preset llhq"; } // webm @@ -683,9 +683,9 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(levelString)) { - // h264_qsv and libnvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { switch (levelString) { @@ -729,7 +729,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 133cc8d70..e2348e8df 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "libopus", //"libvorbis", "srt", - "libnvenc", + "h264_nvenc", "h264_qsv" }; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 177009306..7c4b7fc2f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -562,9 +562,9 @@ namespace MediaBrowser.MediaEncoding.Encoder return "h264_qsv"; } - if (string.Equals(options.HardwareAccelerationType, "libnvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(options.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - return "libnvenc"; + return "h264_nvenc"; } if (string.Equals(options.HardwareAccelerationType, "h264_omx", StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From 580a68d19c52a48792c0d714da98e99b08a51b1d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Jun 2016 21:06:18 -0400 Subject: update startup tests --- .../Serialization/JsonSerializer.cs | 2 +- .../Serialization/XmlSerializer.cs | 4 ++-- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 12 +++++++----- MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs index dfd4b02d0..5dbbe5373 100644 --- a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs +++ b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Common.Implementations.Serialization private Stream OpenFile(string path) { - _logger.Info("Deserializing file {0}", path); + _logger.Debug("Deserializing file {0}", path); return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072); } diff --git a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs index 5996f02d3..756741e0d 100644 --- a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs +++ b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Common.Implementations.Serialization /// The file. public void SerializeToFile(object obj, string file) { - _logger.Info("Serializing to file {0}", file); + _logger.Debug("Serializing to file {0}", file); using (var stream = new FileStream(file, FileMode.Create)) { SerializeToStream(obj, stream); @@ -95,7 +95,7 @@ namespace MediaBrowser.Common.Implementations.Serialization /// System.Object. public object DeserializeFromFile(Type type, string file) { - _logger.Info("Deserializing file {0}", file); + _logger.Debug("Deserializing file {0}", file); using (var stream = _fileSystem.OpenRead(file)) { return DeserializeFromStream(type, stream); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index e2348e8df..23e3d0fa6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -78,17 +78,19 @@ namespace MediaBrowser.MediaEncoding.Encoder "libx265", "mpeg4", "msmpeg4", - //"libvpx", - //"libvpx-vp9", + "libvpx", + "libvpx-vp9", "aac", "libmp3lame", "libopus", - //"libvorbis", + "libvorbis", "srt", "h264_nvenc", "h264_qsv" }; + output = output ?? string.Empty; + foreach (var codec in required) { var srch = " " + codec + " "; @@ -116,7 +118,7 @@ namespace MediaBrowser.MediaEncoding.Encoder WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, RedirectStandardOutput = true, - RedirectStandardError = true + //RedirectStandardError = true } }; @@ -126,7 +128,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - process.BeginErrorReadLine(); + //process.BeginErrorReadLine(); return process.StandardOutput.ReadToEnd(); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 25adbcdb0..9a83aba88 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -455,7 +455,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw; } - + var logTask = process.StandardError.BaseStream.CopyToAsync(logFileStream); var ranToCompletion = process.WaitForExit(60000); -- cgit v1.2.3 From 00634b62c53d145e3dc6ad707dfbe98cb21bfa5a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 30 Jun 2016 22:35:18 -0400 Subject: remove standard output redirect on image extractions --- .../MediaEncoding/IMediaEncoder.cs | 6 ++-- .../Encoder/EncoderValidator.cs | 5 +-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 37 ++++++++-------------- .../MediaInfo/AudioImageProvider.cs | 15 ++++++--- .../MediaInfo/VideoImageProvider.cs | 9 +++--- .../MediaEncoder/EncodingManager.cs | 14 +++++--- 6 files changed, 41 insertions(+), 45 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 62377b19e..c8a8caa91 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// Index of the image stream. /// The cancellation token. /// Task{Stream}. - Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken); + Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken); /// /// Extracts the video image. @@ -46,9 +46,9 @@ namespace MediaBrowser.Controller.MediaEncoding /// The offset. /// The cancellation token. /// Task{Stream}. - Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); - Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken); + Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken); /// /// Extracts the video images on interval. diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 23e3d0fa6..859452362 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -117,8 +117,7 @@ namespace MediaBrowser.MediaEncoding.Encoder Arguments = arguments, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - RedirectStandardOutput = true, - //RedirectStandardError = true + RedirectStandardOutput = true } }; @@ -128,8 +127,6 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - //process.BeginErrorReadLine(); - return process.StandardOutput.ReadToEnd(); } catch diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7264ad2d1..68113c0d1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -767,22 +767,22 @@ namespace MediaBrowser.MediaEncoding.Encoder /// protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) + public Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) { return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken); } - public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) + public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken); } - public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken) + public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken) { return ExtractImage(inputFiles, imageStreamIndex, protocol, false, null, null, cancellationToken); } - private async Task ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio, + private async Task ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool; @@ -816,13 +816,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false); } - private async Task ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken) + private async Task ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { throw new ArgumentNullException("inputPath"); } + var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg"); + Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath)); + // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar var vf = "scale=600:trunc(600/dar/2)*2"; @@ -855,8 +858,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty; // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var args = useIFrame ? string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf, mapArg) : - string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf, mapArg); + var args = useIFrame ? string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg) : + string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol); @@ -880,8 +883,6 @@ namespace MediaBrowser.MediaEncoding.Encoder Arguments = args, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, - RedirectStandardOutput = true, - RedirectStandardError = true, RedirectStandardInput = true } }; @@ -894,20 +895,10 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion; - var memoryStream = new MemoryStream(); - try { StartProcess(processWrapper); -#pragma warning disable 4014 - // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - process.StandardOutput.BaseStream.CopyToAsync(memoryStream); -#pragma warning restore 4014 - - // MUST read both stdout and stderr asynchronously or a deadlock may occurr - process.BeginErrorReadLine(); - ranToCompletion = process.WaitForExit(10000); if (!ranToCompletion) @@ -922,11 +913,10 @@ namespace MediaBrowser.MediaEncoding.Encoder } var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; + var file = new FileInfo(tempExtractPath); - if (exitCode == -1 || memoryStream.Length == 0) + if (exitCode == -1 || !file.Exists || file.Length == 0) { - memoryStream.Dispose(); - var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath); _logger.Error(msg); @@ -934,8 +924,7 @@ namespace MediaBrowser.MediaEncoding.Encoder throw new ApplicationException(msg); } - memoryStream.Position = 0; - return memoryStream; + return tempExtractPath; } } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 4b795a474..bec9280b3 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -83,12 +83,17 @@ namespace MediaBrowser.Providers.MediaInfo var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index; - using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false)) + var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false); + + File.Copy(tempFile, path, true); + + try { - using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) - { - await stream.CopyToAsync(fileStream).ConfigureAwait(false); - } + File.Delete(tempFile); + } + catch + { + } } } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index ff6eef167..9a1f072cd 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.MediaInfo imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? imageStreams.FirstOrDefault(); - Stream stream; + string extractedImagePath; if (imageStream != null) { @@ -135,7 +135,7 @@ namespace MediaBrowser.Providers.MediaInfo } } - stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false); + extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false); } else { @@ -146,14 +146,15 @@ namespace MediaBrowser.Providers.MediaInfo ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1)) : TimeSpan.FromSeconds(10); - stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); + extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); } return new DynamicImageResponse { Format = ImageFormat.Jpg, HasImage = true, - Stream = stream + Path = extractedImagePath, + Protocol = MediaProtocol.File }; } finally diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index a7b0d61c7..b1b2072c4 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -139,12 +139,16 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder { _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - using (var stream = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false)) + var tempFile = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); + File.Copy(tempFile, path, true); + + try + { + File.Delete(tempFile); + } + catch { - using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) - { - await stream.CopyToAsync(fileStream).ConfigureAwait(false); - } + } chapter.ImagePath = path; -- cgit v1.2.3 From 42b6e88aa7337a82a08e699c6e63ca09972d9ef6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 7 Jul 2016 23:21:06 -0400 Subject: fix validation logging --- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 859452362..0866bd255 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -86,20 +86,28 @@ namespace MediaBrowser.MediaEncoding.Encoder "libvorbis", "srt", "h264_nvenc", - "h264_qsv" + "h264_qsv", + "ac3" }; output = output ?? string.Empty; + var index = 0; + foreach (var codec in required) { var srch = " " + codec + " "; if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) != -1) { - _logger.Info("Encoder available: " + codec); + if (index < required.Length - 1) + { + _logger.Info("Encoder available: " + codec); + } + found.Add(codec); } + index++; } return found; -- cgit v1.2.3