From 60ac2e87129a1911ed518ea21977b1f689da015d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 27 Oct 2015 10:02:30 -0400 Subject: rework shutdown --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 7e9fa151b..56ce6b6d6 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -130,13 +130,18 @@ namespace MediaBrowser.MediaEncoding.Probing var stream = new MediaStream { Codec = streamInfo.codec_name, - CodecTag = streamInfo.codec_tag_string, Profile = streamInfo.profile, Level = streamInfo.level, Index = streamInfo.index, PixelFormat = streamInfo.pix_fmt }; + // Filter out junk + if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) + { + stream.CodecTag = streamInfo.codec_tag_string; + } + if (streamInfo.tags != null) { stream.Language = GetDictionaryValue(streamInfo.tags, "language"); -- cgit v1.2.3 From b5f0cc5ad7fd5976b20673e631cf155e432b7230 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 10 Nov 2015 23:11:14 -0500 Subject: use int tryparse --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index ddcd48b8b..d4df19af2 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -49,7 +49,11 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(data.format.bit_rate)) { - info.Bitrate = int.Parse(data.format.bit_rate, _usCulture); + int value; + if (int.TryParse(data.format.bit_rate, NumberStyles.Any, _usCulture, out value)) + { + info.Bitrate = value; + } } } -- cgit v1.2.3 From 532af874522aaa46dc1cec66789632aafeda1849 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Nov 2015 23:34:11 -0500 Subject: update qsv encoding --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 ++-- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 2 +- MediaBrowser.Model/Configuration/EncodingOptions.cs | 4 ++-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 1b5e6e865..43866889f 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -288,7 +288,7 @@ namespace MediaBrowser.Api.Playback protected string GetH264Encoder(StreamState state) { - if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { // It's currently failing on live tv if (state.RunTimeTicks.HasValue) @@ -820,7 +820,7 @@ namespace MediaBrowser.Api.Playback /// System.String. protected string GetVideoDecoder(StreamState state) { - if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 912110c04..98e4a58a6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -359,7 +359,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// System.String. protected string GetVideoDecoder(EncodingJob state) { - if (string.Equals(GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) { diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 77aa9e683..b41ad7eb0 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -9,13 +9,13 @@ namespace MediaBrowser.Model.Configuration public bool EnableDebugLogging { get; set; } public bool EnableThrottling { get; set; } public int ThrottleThresholdSeconds { get; set; } - public string HardwareVideoDecoder { get; set; } + public string HardwareAccelerationType { get; set; } public EncodingOptions() { DownMixAudioBoost = 2; EnableThrottling = true; - ThrottleThresholdSeconds = 100; + ThrottleThresholdSeconds = 110; EncodingThreadCount = -1; } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index a237bb226..fb8e77006 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -234,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun int? width = null; int? height = null; bool isInterlaced = true; - var videoCodec = !string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareVideoDecoder) ? null : "mpeg2video"; + var videoCodec = !string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType) ? null : "mpeg2video"; int? videoBitrate = null; -- cgit v1.2.3 From 3060b0c5e98583d390c7acb634f57af90f9e1954 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 10 Dec 2015 23:48:28 -0500 Subject: update sorting menus --- MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 692fe2b6a..cf776b3f7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -502,7 +502,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { return "libx264"; } - if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) { return "libx265"; } -- cgit v1.2.3 From 02938e7bcb0459a44dfa6c9e7dfa2a04be3467be Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Dec 2015 01:49:03 -0500 Subject: update keyframe setting --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 + MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 42 +----- .../Playback/Progressive/VideoService.cs | 1 + .../MediaEncoding/MediaInfoRequest.cs | 1 - MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 157 +-------------------- .../Configuration/ServerConfiguration.cs | 2 - MediaBrowser.Model/Entities/MediaStream.cs | 3 - .../MediaInfo/FFProbeVideoInfo.cs | 3 +- .../Persistence/SqliteItemRepository.cs | 23 +-- MediaBrowser.WebDashboard/Api/DashboardService.cs | 5 + 10 files changed, 15 insertions(+), 224 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a940be763..eacd7999c 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2178,6 +2178,8 @@ namespace MediaBrowser.Api.Playback inputModifier += " " + videoDecoder; } + //inputModifier += " -noaccurate_seek"; + return inputModifier; } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 3724c8868..c6abffd07 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -291,25 +291,6 @@ namespace MediaBrowser.Api.Playback.Hls private double[] GetSegmentLengths(StreamState state) { var result = new List(); - if (state.VideoRequest != null) - { - var encoder = GetVideoEncoder(state); - - if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase)) - { - var videoStream = state.VideoStream; - if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0) - { - foreach (var frame in videoStream.KeyFrames) - { - var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds; - seconds -= result.Sum(); - result.Add(seconds); - } - return result.ToArray(); - } - } - } var ticks = state.RunTimeTicks ?? 0; @@ -936,27 +917,8 @@ namespace MediaBrowser.Api.Playback.Hls protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream) { - if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0) - { - Logger.Debug("Cannot stream copy video due to missing keyframe info"); - return false; - } - - var previousSegment = 0; - foreach (var frame in videoStream.KeyFrames) - { - var length = frame - previousSegment; - - // Don't allow really long segments because this could result in long download times - if (length > 10000) - { - Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length); - return false; - } - previousSegment = frame; - } - - return base.CanStreamCopyVideo(request, videoStream); + return false; + //return base.CanStreamCopyVideo(request, videoStream); } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index d79040dd4..519bfa8d8 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -100,6 +100,7 @@ namespace MediaBrowser.Api.Playback.Progressive { // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js format = " -f mp4 -movflags frag_keyframe+empty_moov"; + //format = " -avoid_negative_ts disabled -start_at_zero -copyts -f mp4 -movflags frag_keyframe+empty_moov"; } var threads = GetNumberOfThreads(state, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs index 24df7b885..ca0c2fdbb 100644 --- a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs +++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs @@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding public IIsoMount MountedIso { get; set; } public VideoType VideoType { get; set; } public List PlayableStreamFileNames { get; set; } - public bool ExtractKeyFrameInterval { get; set; } public MediaInfoRequest() { diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index c8361ea04..a61b15ac5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -135,9 +135,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames); - var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile; - - return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval, + return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); } @@ -171,18 +169,16 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The primary path. /// The protocol. /// if set to true [extract chapters]. - /// if set to true [extract key frame interval]. /// The probe size argument. /// if set to true [is audio]. /// Type of the video. /// The cancellation token. /// Task{MediaInfoResult}. - /// + /// ffprobe failed - streams and format are both null. private async Task GetMediaInfoInternal(string inputPath, string primaryPath, MediaProtocol protocol, bool extractChapters, - bool extractKeyFrameInterval, string probeSizeArgument, bool isAudio, VideoType videoType, @@ -262,31 +258,6 @@ namespace MediaBrowser.MediaEncoding.Encoder var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); - if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) - { - if (ConfigurationManager.Configuration.EnableVideoFrameByFrameAnalysis && mediaInfo.Size.HasValue) - { - foreach (var stream in mediaInfo.MediaStreams) - { - if (EnableKeyframeExtraction(mediaInfo, stream)) - { - try - { - stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error getting key frame interval", ex); - } - } - } - } - } - return mediaInfo; } catch @@ -300,132 +271,8 @@ namespace MediaBrowser.MediaEncoding.Encoder _ffProbeResourcePool.Release(); } } - - throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath)); - } - - private bool EnableKeyframeExtraction(MediaSourceInfo mediaSource, MediaStream videoStream) - { - if (videoStream.Type == MediaStreamType.Video && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) && - !videoStream.IsInterlaced && - !(videoStream.IsAnamorphic ?? false)) - { - var audioStreams = mediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList(); - - // If it has aac audio then it will probably direct stream anyway, so don't bother with this - if (audioStreams.Count == 1 && string.Equals(audioStreams[0].Codec, "aac", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return true; - } - return false; - } - - private async Task> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken) - { - inputPath = inputPath.Split(new[] { ':' }, 2).Last().Trim('"'); - - const string args = "-show_packets -print_format compact -select_streams v:{1} -show_entries packet=flags -show_entries packet=pts_time \"{0}\""; - - var process = new Process - { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - - // Must consume both or ffmpeg may hang due to deadlocks. See comments below. - RedirectStandardOutput = true, - RedirectStandardError = true, - FileName = FFProbePath, - Arguments = string.Format(args, inputPath, videoStreamIndex.ToString(CultureInfo.InvariantCulture)).Trim(), - - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - - EnableRaisingEvents = true - }; - - _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - - using (process) - { - var start = DateTime.UtcNow; - - process.Start(); - - var lines = new List(); - - try - { - process.BeginErrorReadLine(); - - await StartReadingOutput(process.StandardOutput.BaseStream, lines, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - if (cancellationToken.IsCancellationRequested) - { - throw; - } - } - - process.WaitForExit(); - - _logger.Info("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds); - //_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray())); - return lines; - } } - private async Task StartReadingOutput(Stream source, List keyframes, CancellationToken cancellationToken) - { - try - { - using (var reader = new StreamReader(source)) - { - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - - var lines = StringHelper.RegexSplit(text, "[\r\n]+"); - foreach (var line in lines) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var values = line.Split('|') - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Select(i => i.Split('=')) - .Where(i => i.Length == 2) - .ToDictionary(i => i[0], i => i[1]); - - string flags; - if (values.TryGetValue("flags", out flags) && string.Equals(flags, "k", StringComparison.OrdinalIgnoreCase)) - { - string pts_time; - double frameSeconds; - if (values.TryGetValue("pts_time", out pts_time) && double.TryParse(pts_time, NumberStyles.Any, CultureInfo.InvariantCulture, out frameSeconds)) - { - var ms = frameSeconds * 1000; - keyframes.Add(Convert.ToInt32(ms)); - } - } - } - } - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffprobe output", ex); - } - } /// /// The us culture /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 5666a32be..08f7f89e3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -209,8 +209,6 @@ namespace MediaBrowser.Model.Configuration public bool EnableWindowsShortcuts { get; set; } - public bool EnableVideoFrameByFrameAnalysis { get; set; } - public bool EnableDateLastRefresh { get; set; } public string[] Migrations { get; set; } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 79d1df911..d089f0aa9 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -233,8 +233,5 @@ namespace MediaBrowser.Model.Entities /// /// null if [is cabac] contains no value, true if [is cabac]; otherwise, false. public bool? IsCabac { get; set; } - - [IgnoreDataMember] - public List KeyFrames { get; set; } } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 5a87e7628..4744b3729 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -170,8 +170,7 @@ namespace MediaBrowser.Providers.MediaInfo VideoType = item.VideoType, MediaType = DlnaProfileType.Video, InputPath = item.Path, - Protocol = protocol, - ExtractKeyFrameInterval = true + Protocol = protocol }, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 6b834bbf2..1d3ac293e 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, KeyFrames TEXT NULL, CodecTag TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -385,7 +385,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "IsAnamorphic", "RefFrames", "IsCabac", - "KeyFrames", "CodecTag" }; @@ -2683,15 +2682,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; _saveStreamCommand.GetParameter(index++).Value = stream.IsCabac; - if (stream.KeyFrames == null || stream.KeyFrames.Count == 0) - { - _saveStreamCommand.GetParameter(index++).Value = null; - } - else - { - _saveStreamCommand.GetParameter(index++).Value = string.Join(",", stream.KeyFrames.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()); - } - _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.Transaction = transaction; @@ -2848,16 +2838,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!reader.IsDBNull(26)) { - var frames = reader.GetString(26); - if (!string.IsNullOrWhiteSpace(frames)) - { - item.KeyFrames = frames.Split(',').Select(i => int.Parse(i, CultureInfo.InvariantCulture)).ToList(); - } - } - - if (!reader.IsDBNull(27)) - { - item.CodecTag = reader.GetString(27); + item.CodecTag = reader.GetString(26); } return item; diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index d24a4a3de..c16c63578 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -303,6 +303,11 @@ namespace MediaBrowser.WebDashboard.Api var mode = request.Mode; + if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) + { + _fileSystem.DeleteFile(Path.Combine(path, "scripts", "registrationservices.js")); + } + // Try to trim the output size a bit var bowerPath = Path.Combine(path, "bower_components"); DeleteFilesByExtension(bowerPath, ".log"); -- cgit v1.2.3 From 5963affec5b492d4859017cfd9352dfd683b3795 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 10:56:07 -0500 Subject: fix merge conflict --- .../MediaBrowser.MediaEncoding.csproj | 4 - .../Probing/ProbeResultNormalizer.cs | 34 +-- .../MediaBrowser.MediaInfo.csproj | 58 ----- MediaBrowser.MediaInfo/MediaInfoLib.cs | 65 ----- MediaBrowser.MediaInfo/Native.cs | 275 --------------------- MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs | 31 --- .../MediaBrowser.Server.Mono.csproj | 4 - MediaBrowser.sln | 23 -- 8 files changed, 11 insertions(+), 483 deletions(-) delete mode 100644 MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj delete mode 100644 MediaBrowser.MediaInfo/MediaInfoLib.cs delete mode 100644 MediaBrowser.MediaInfo/Native.cs delete mode 100644 MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 1f74994e5..df5ab4651 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -99,10 +99,6 @@ {17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2} MediaBrowser.Controller - - {6e4145e4-c6d4-4e4d-94f2-87188db6e239} - MediaBrowser.MediaInfo - {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index d4df19af2..55b3398bb 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.IO; -using MediaBrowser.MediaInfo; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; @@ -26,7 +25,7 @@ namespace MediaBrowser.MediaEncoding.Probing _fileSystem = fileSystem; } - public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType videoType, bool isAudio, string path, MediaProtocol protocol) + public MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType videoType, bool isAudio, string path, MediaProtocol protocol) { var info = new Model.MediaInfo.MediaInfo { @@ -109,7 +108,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (videoStream != null && videoType == VideoType.VideoFile) { - UpdateFromMediaInfo(info, videoStream); + DetectInterlaced(info, videoStream); } } @@ -934,29 +933,18 @@ namespace MediaBrowser.MediaEncoding.Probing return TransportStreamTimestamp.None; } - private void UpdateFromMediaInfo(MediaSourceInfo video, MediaStream videoStream) + private void DetectInterlaced(MediaSourceInfo video, MediaStream videoStream) { - if (video.Protocol == MediaProtocol.File && videoStream != null) + if (video.Protocol != MediaProtocol.File || videoStream == null) { - try - { - _logger.Debug("Running MediaInfo against {0}", video.Path); - - var result = new MediaInfoLib().GetVideoInfo(video.Path); + return; + } - videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac; - videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced; - videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth; - videoStream.RefFrames = result.RefFrames ?? videoStream.RefFrames; - } - catch (TypeLoadException) - { - // This is non-essential. Don't spam the log - } - catch (Exception ex) - { - _logger.ErrorException("Error running MediaInfo on {0}", ex, video.Path); - } + // Take a shortcut and limit this to containers that are likely to have interlaced content + if (!string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase) && + !string.Equals(video.Container, "wtv", StringComparison.OrdinalIgnoreCase)) + { + return; } } } diff --git a/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj b/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj deleted file mode 100644 index 024098cb9..000000000 --- a/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj +++ /dev/null @@ -1,58 +0,0 @@ - - - - - Debug - AnyCPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239} - Library - Properties - MediaBrowser.MediaInfo - MediaBrowser.MediaInfo - v4.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - none - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - Properties\SharedVersion.cs - - - - - - - - - \ No newline at end of file diff --git a/MediaBrowser.MediaInfo/MediaInfoLib.cs b/MediaBrowser.MediaInfo/MediaInfoLib.cs deleted file mode 100644 index fa644aee0..000000000 --- a/MediaBrowser.MediaInfo/MediaInfoLib.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; - -namespace MediaBrowser.MediaInfo -{ - public class MediaInfoLib - { - public MediaInfoResult GetVideoInfo(string path) - { - var lib = new MediaInfo(); - - lib.Open(path); - - var result = new MediaInfoResult(); - - // TODO: Don't hardcode - var videoStreamIndex = 0; - - var text = GetValue(lib, videoStreamIndex, new[] { "ScanType", "Scan type", "ScanType/String" }); - if (!string.IsNullOrWhiteSpace(text)) - { - result.IsInterlaced = text.IndexOf("interlac", StringComparison.OrdinalIgnoreCase) != -1; - } - - text = GetValue(lib, videoStreamIndex, new[] { "Format_Settings_CABAC", "Format_Settings_CABAC/String" }); - if (!string.IsNullOrWhiteSpace(text)) - { - result.IsCabac = string.Equals(text, "yes", StringComparison.OrdinalIgnoreCase); - } - - int bitDepth; - text = GetValue(lib, videoStreamIndex, new[] { "BitDepth", "BitDepth/String" }); - - if (!string.IsNullOrWhiteSpace(text) && int.TryParse(text.Split(' ').First(), NumberStyles.Any, CultureInfo.InvariantCulture, out bitDepth)) - { - result.BitDepth = bitDepth; - } - - int refFrames; - text = GetValue(lib, videoStreamIndex, new[] { "Format_Settings_RefFrames", "Format_Settings_RefFrames/String" }); - - if (!string.IsNullOrWhiteSpace(text) && int.TryParse(text.Split(' ').First(), NumberStyles.Any, CultureInfo.InvariantCulture, out refFrames)) - { - result.RefFrames = refFrames; - } - - return result; - } - - private string GetValue(MediaInfo lib, int index, IEnumerable names) - { - return names.Select(i => lib.Get(StreamKind.Video, index, i)).FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - } - - public class MediaInfoResult - { - public bool? IsCabac { get; set; } - public bool? IsInterlaced { get; set; } - public int? BitDepth { get; set; } - public int? RefFrames { get; set; } - } -} diff --git a/MediaBrowser.MediaInfo/Native.cs b/MediaBrowser.MediaInfo/Native.cs deleted file mode 100644 index 5bc7ae368..000000000 --- a/MediaBrowser.MediaInfo/Native.cs +++ /dev/null @@ -1,275 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace MediaBrowser.MediaInfo -{ - public enum StreamKind - { - General, - Video, - Audio, - Text, - Other, - Image, - Menu, - } - - public enum InfoKind - { - Name, - Text, - Measure, - Options, - NameText, - MeasureText, - Info, - HowTo - } - - public enum InfoOptions - { - ShowInInform, - Support, - ShowInSupported, - TypeOfValue - } - - public enum InfoFileOptions - { - FileOption_Nothing = 0x00, - FileOption_NoRecursive = 0x01, - FileOption_CloseAll = 0x02, - FileOption_Max = 0x04 - }; - - public enum Status - { - None = 0x00, - Accepted = 0x01, - Filled = 0x02, - Updated = 0x04, - Finalized = 0x08, - } - - public class MediaInfo - { - //Import of DLL functions. DO NOT USE until you know what you do (MediaInfo DLL do NOT use CoTaskMemAlloc to allocate memory) - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_New(); - [DllImport("MediaInfo")] - private static extern void MediaInfo_Delete(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Open(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string FileName); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Open(IntPtr Handle, IntPtr FileName); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Open_Buffer_Init(IntPtr Handle, Int64 File_Size, Int64 File_Offset); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Open(IntPtr Handle, Int64 File_Size, Int64 File_Offset); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Open_Buffer_Continue(IntPtr Handle, IntPtr Buffer, IntPtr Buffer_Size); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Open_Buffer_Continue(IntPtr Handle, Int64 File_Size, byte[] Buffer, IntPtr Buffer_Size); - [DllImport("MediaInfo")] - private static extern Int64 MediaInfo_Open_Buffer_Continue_GoTo_Get(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern Int64 MediaInfoA_Open_Buffer_Continue_GoTo_Get(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Open_Buffer_Finalize(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Open_Buffer_Finalize(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern void MediaInfo_Close(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Inform(IntPtr Handle, IntPtr Reserved); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Inform(IntPtr Handle, IntPtr Reserved); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_GetI(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_GetI(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, [MarshalAs(UnmanagedType.LPWStr)] string Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Option(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string Option, [MarshalAs(UnmanagedType.LPWStr)] string Value); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoA_Option(IntPtr Handle, IntPtr Option, IntPtr Value); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_State_Get(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfo_Count_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber); - - //MediaInfo class - public MediaInfo() - { - try - { - Handle = MediaInfo_New(); - } - catch - { - Handle = (IntPtr)0; - } - if (Environment.OSVersion.ToString().IndexOf("Windows") == -1) - MustUseAnsi = true; - else - MustUseAnsi = false; - } - ~MediaInfo() { if (Handle == (IntPtr)0) return; MediaInfo_Delete(Handle); } - public int Open(String FileName) - { - if (Handle == (IntPtr)0) - return 0; - if (MustUseAnsi) - { - IntPtr FileName_Ptr = Marshal.StringToHGlobalAnsi(FileName); - int ToReturn = (int)MediaInfoA_Open(Handle, FileName_Ptr); - Marshal.FreeHGlobal(FileName_Ptr); - return ToReturn; - } - else - return (int)MediaInfo_Open(Handle, FileName); - } - public int Open_Buffer_Init(Int64 File_Size, Int64 File_Offset) - { - if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Init(Handle, File_Size, File_Offset); - } - public int Open_Buffer_Continue(IntPtr Buffer, IntPtr Buffer_Size) - { - if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Continue(Handle, Buffer, Buffer_Size); - } - public Int64 Open_Buffer_Continue_GoTo_Get() - { - if (Handle == (IntPtr)0) return 0; return (Int64)MediaInfo_Open_Buffer_Continue_GoTo_Get(Handle); - } - public int Open_Buffer_Finalize() - { - if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Finalize(Handle); - } - public void Close() { if (Handle == (IntPtr)0) return; MediaInfo_Close(Handle); } - public String Inform() - { - if (Handle == (IntPtr)0) - return "Unable to load MediaInfo library"; - if (MustUseAnsi) - return Marshal.PtrToStringAnsi(MediaInfoA_Inform(Handle, (IntPtr)0)); - else - return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, (IntPtr)0)); - } - public String Get(StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo, InfoKind KindOfSearch) - { - if (Handle == (IntPtr)0) - return "Unable to load MediaInfo library"; - if (MustUseAnsi) - { - IntPtr Parameter_Ptr = Marshal.StringToHGlobalAnsi(Parameter); - String ToReturn = Marshal.PtrToStringAnsi(MediaInfoA_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter_Ptr, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); - Marshal.FreeHGlobal(Parameter_Ptr); - return ToReturn; - } - else - return Marshal.PtrToStringUni(MediaInfo_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); - } - public String Get(StreamKind StreamKind, int StreamNumber, int Parameter, InfoKind KindOfInfo) - { - if (Handle == (IntPtr)0) - return "Unable to load MediaInfo library"; - if (MustUseAnsi) - return Marshal.PtrToStringAnsi(MediaInfoA_GetI(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); - else - return Marshal.PtrToStringUni(MediaInfo_GetI(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); - } - public String Option(String Option, String Value) - { - if (Handle == (IntPtr)0) - return "Unable to load MediaInfo library"; - if (MustUseAnsi) - { - IntPtr Option_Ptr = Marshal.StringToHGlobalAnsi(Option); - IntPtr Value_Ptr = Marshal.StringToHGlobalAnsi(Value); - String ToReturn = Marshal.PtrToStringAnsi(MediaInfoA_Option(Handle, Option_Ptr, Value_Ptr)); - Marshal.FreeHGlobal(Option_Ptr); - Marshal.FreeHGlobal(Value_Ptr); - return ToReturn; - } - else - return Marshal.PtrToStringUni(MediaInfo_Option(Handle, Option, Value)); - } - public int State_Get() { if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_State_Get(Handle); } - public int Count_Get(StreamKind StreamKind, int StreamNumber) { if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Count_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber); } - private IntPtr Handle; - private bool MustUseAnsi; - - //Default values, if you know how to set default values in C#, say me - public String Get(StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo) { return Get(StreamKind, StreamNumber, Parameter, KindOfInfo, InfoKind.Name); } - public String Get(StreamKind StreamKind, int StreamNumber, String Parameter) { return Get(StreamKind, StreamNumber, Parameter, InfoKind.Text, InfoKind.Name); } - public String Get(StreamKind StreamKind, int StreamNumber, int Parameter) { return Get(StreamKind, StreamNumber, Parameter, InfoKind.Text); } - public String Option(String Option_) { return Option(Option_, ""); } - public int Count_Get(StreamKind StreamKind) { return Count_Get(StreamKind, -1); } - } - - - - - - - - - - - - - - - - - - public class MediaInfoList - { - //Import of DLL functions. DO NOT USE until you know what you do (MediaInfo DLL do NOT use CoTaskMemAlloc to allocate memory) - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_New(); - [DllImport("MediaInfo")] - private static extern void MediaInfoList_Delete(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_Open(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string FileName, IntPtr Options); - [DllImport("MediaInfo")] - private static extern void MediaInfoList_Close(IntPtr Handle, IntPtr FilePos); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_Inform(IntPtr Handle, IntPtr FilePos, IntPtr Reserved); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_GetI(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_Get(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber, [MarshalAs(UnmanagedType.LPWStr)] string Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_Option(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string Option, [MarshalAs(UnmanagedType.LPWStr)] string Value); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_State_Get(IntPtr Handle); - [DllImport("MediaInfo")] - private static extern IntPtr MediaInfoList_Count_Get(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber); - - //MediaInfo class - public MediaInfoList() { Handle = MediaInfoList_New(); } - ~MediaInfoList() { MediaInfoList_Delete(Handle); } - public int Open(String FileName, InfoFileOptions Options) { return (int)MediaInfoList_Open(Handle, FileName, (IntPtr)Options); } - public void Close(int FilePos) { MediaInfoList_Close(Handle, (IntPtr)FilePos); } - public String Inform(int FilePos) { return Marshal.PtrToStringUni(MediaInfoList_Inform(Handle, (IntPtr)FilePos, (IntPtr)0)); } - public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo, InfoKind KindOfSearch) { return Marshal.PtrToStringUni(MediaInfoList_Get(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); } - public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, int Parameter, InfoKind KindOfInfo) { return Marshal.PtrToStringUni(MediaInfoList_GetI(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); } - public String Option(String Option, String Value) { return Marshal.PtrToStringUni(MediaInfoList_Option(Handle, Option, Value)); } - public int State_Get() { return (int)MediaInfoList_State_Get(Handle); } - public int Count_Get(int FilePos, StreamKind StreamKind, int StreamNumber) { return (int)MediaInfoList_Count_Get(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber); } - private IntPtr Handle; - - //Default values, if you know how to set default values in C#, say me - public void Open(String FileName) { Open(FileName, 0); } - public void Close() { Close(-1); } - public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo) { return Get(FilePos, StreamKind, StreamNumber, Parameter, KindOfInfo, InfoKind.Name); } - public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter) { return Get(FilePos, StreamKind, StreamNumber, Parameter, InfoKind.Text, InfoKind.Name); } - public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, int Parameter) { return Get(FilePos, StreamKind, StreamNumber, Parameter, InfoKind.Text); } - public String Option(String Option_) { return Option(Option_, ""); } - public int Count_Get(int FilePos, StreamKind StreamKind) { return Count_Get(FilePos, StreamKind, -1); } - } -} diff --git a/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs b/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs deleted file mode 100644 index 8249bd33c..000000000 --- a/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.MediaInfo")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.MediaInfo")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("8ef5ed2a-0460-4fb4-ba3f-fc2ba057f009")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 8b2b19c58..e9f631bf3 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -144,10 +144,6 @@ - - MediaInfo\osx\libmediainfo.dylib - PreserveNewest - libsqlite3.0.dylib PreserveNewest diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 0dadf9136..a9b5020ec 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -56,8 +56,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaInfo", "MediaBrowser.MediaInfo\MediaBrowser.MediaInfo.csproj", "{6E4145E4-C6D4-4E4D-94F2-87188DB6E239}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Mono", "MediaBrowser.Server.Mono\MediaBrowser.Server.Mono.csproj", "{175A9388-F352-4586-A6B4-070DED62B644}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Startup.Common", "MediaBrowser.Server.Startup.Common\MediaBrowser.Server.Startup.Common.csproj", "{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}" @@ -451,27 +449,6 @@ Global {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Win32.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x64.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|x64.ActiveCfg = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Debug|x86.ActiveCfg = Debug|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|Any CPU.Build.0 = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|Mixed Platforms.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|Mixed Platforms.Build.0 = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|Win32.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|x64.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release Mono|x86.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|Any CPU.Build.0 = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|Win32.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|x64.ActiveCfg = Release|Any CPU - {6E4145E4-C6D4-4E4D-94F2-87188DB6E239}.Release|x86.ActiveCfg = Release|Any CPU {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Any CPU.ActiveCfg = Debug|x86 {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Any CPU.Build.0 = Debug|x86 {175A9388-F352-4586-A6B4-070DED62B644}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 -- cgit v1.2.3 From 949d23f06aeff62f1cd38ddf074b89a1307eedb0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 12:45:50 -0500 Subject: fix merge conflict --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 346 ++++++++++++++++++++- 1 file changed, 344 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a61b15ac5..1dc1a4215 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -135,7 +135,9 @@ namespace MediaBrowser.MediaEncoding.Encoder var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames); - return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, + var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile; + + return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval, GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); } @@ -169,16 +171,18 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The primary path. /// The protocol. /// if set to true [extract chapters]. + /// if set to true [extract key frame interval]. /// The probe size argument. /// if set to true [is audio]. /// Type of the video. /// The cancellation token. /// Task{MediaInfoResult}. - /// ffprobe failed - streams and format are both null. + /// private async Task GetMediaInfoInternal(string inputPath, string primaryPath, MediaProtocol protocol, bool extractChapters, + bool extractKeyFrameInterval, string probeSizeArgument, bool isAudio, VideoType videoType, @@ -258,6 +262,43 @@ namespace MediaBrowser.MediaEncoding.Encoder var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); + + if (videoStream != null) + { + var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); + + if (isInterlaced) + { + videoStream.IsInterlaced = true; + } + } + + if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) + { + if (ConfigurationManager.Configuration.EnableVideoFrameByFrameAnalysis && mediaInfo.Size.HasValue) + { + foreach (var stream in mediaInfo.MediaStreams) + { + if (EnableKeyframeExtraction(mediaInfo, stream)) + { + try + { + stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + + } + catch (Exception ex) + { + _logger.ErrorException("Error getting key frame interval", ex); + } + } + } + } + } + return mediaInfo; } catch @@ -271,8 +312,309 @@ namespace MediaBrowser.MediaEncoding.Encoder _ffProbeResourcePool.Release(); } } + + throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath)); + } + + private async Task DetectInterlaced(MediaSourceInfo video, MediaStream videoStream, string inputPath, string probeSizeArgument) + { + if (video.Protocol != MediaProtocol.File) + { + return false; + } + + var formats = (video.Container ?? string.Empty).Split(',').ToList(); + + // Take a shortcut and limit this to containers that are likely to have interlaced content + if (!formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) + { + return false; + } + + var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null"; + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + + // Must consume both or ffmpeg may hang due to deadlocks. See comments below. + RedirectStandardOutput = true, + RedirectStandardError = true, + RedirectStandardInput = true, + FileName = FFMpegPath, + Arguments = string.Format(args, probeSizeArgument, inputPath, videoStream.Index.ToString(CultureInfo.InvariantCulture)).Trim(), + + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + + EnableRaisingEvents = true + }; + + _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + var idetFoundInterlaced = false; + + using (var processWrapper = new ProcessWrapper(process, this, _logger)) + { + try + { + StartProcess(processWrapper); + } + catch (Exception ex) + { + _logger.ErrorException("Error starting ffprobe", ex); + + throw; + } + + try + { + process.BeginOutputReadLine(); + + using (var reader = new StreamReader(process.StandardError.BaseStream)) + { + while (!reader.EndOfStream) + { + var line = await reader.ReadLineAsync().ConfigureAwait(false); + + if (line.StartsWith("[Parsed_idet", StringComparison.OrdinalIgnoreCase)) + { + var idetResult = AnalyzeIdetResult(line); + + if (idetResult.HasValue) + { + if (!idetResult.Value) + { + return false; + } + + idetFoundInterlaced = true; + } + } + } + } + + } + catch + { + StopProcess(processWrapper, 100, true); + + throw; + } + } + + return idetFoundInterlaced; + } + + private bool? AnalyzeIdetResult(string line) + { + // As you can see, the filter only guessed one frame as progressive. + // Results like this are pretty typical. So if less than 30% of the detections are in the "Undetermined" category, then I only consider the video to be interlaced if at least 65% of the identified frames are in either the TFF or BFF category. + // In this case (310 + 311)/(622) = 99.8% which is well over the 65% metric. I may refine that number with more testing but I honestly do not believe I will need to. + // http://awel.domblogger.net/videoTranscode/interlace.html + var index = line.IndexOf("detection:", StringComparison.OrdinalIgnoreCase); + + if (index == -1) + { + return null; + } + + line = line.Substring(index).Trim(); + var parts = line.Split(' ').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => i.Trim()).ToList(); + + if (parts.Count < 2) + { + return null; + } + double tff = 0; + double bff = 0; + double progressive = 0; + double undetermined = 0; + double total = 0; + + for (var i = 0; i < parts.Count - 1; i++) + { + var part = parts[i]; + + if (string.Equals(part, "tff:", StringComparison.OrdinalIgnoreCase)) + { + tff = GetNextPart(parts, i); + total += tff; + } + else if (string.Equals(part, "bff:", StringComparison.OrdinalIgnoreCase)) + { + bff = GetNextPart(parts, i); + total += tff; + } + else if (string.Equals(part, "progressive:", StringComparison.OrdinalIgnoreCase)) + { + progressive = GetNextPart(parts, i); + total += progressive; + } + else if (string.Equals(part, "undetermined:", StringComparison.OrdinalIgnoreCase)) + { + undetermined = GetNextPart(parts, i); + total += undetermined; + } + } + + if (total == 0) + { + return null; + } + + if ((undetermined / total) >= .3) + { + return false; + } + + if (((tff + bff) / total) >= .65) + { + return true; + } + + return false; + } + + private int GetNextPart(List parts, int index) + { + var next = parts[index + 1]; + + int value; + if (int.TryParse(next, NumberStyles.Any, CultureInfo.InvariantCulture, out value)) + { + return value; + } + return 0; } + private bool EnableKeyframeExtraction(MediaSourceInfo mediaSource, MediaStream videoStream) + { + if (videoStream.Type == MediaStreamType.Video && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) && + !videoStream.IsInterlaced && + !(videoStream.IsAnamorphic ?? false)) + { + var audioStreams = mediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList(); + + // If it has aac audio then it will probably direct stream anyway, so don't bother with this + if (audioStreams.Count == 1 && string.Equals(audioStreams[0].Codec, "aac", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + return true; + } + return false; + } + + private async Task> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken) + { + inputPath = inputPath.Split(new[] { ':' }, 2).Last().Trim('"'); + + const string args = "-show_packets -print_format compact -select_streams v:{1} -show_entries packet=flags -show_entries packet=pts_time \"{0}\""; + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + + // Must consume both or ffmpeg may hang due to deadlocks. See comments below. + RedirectStandardOutput = true, + RedirectStandardError = true, + FileName = FFProbePath, + Arguments = string.Format(args, inputPath, videoStreamIndex.ToString(CultureInfo.InvariantCulture)).Trim(), + + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + + EnableRaisingEvents = true + }; + + _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + + using (process) + { + var start = DateTime.UtcNow; + + process.Start(); + + var lines = new List(); + + try + { + process.BeginErrorReadLine(); + + await StartReadingOutput(process.StandardOutput.BaseStream, lines, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + if (cancellationToken.IsCancellationRequested) + { + throw; + } + } + + process.WaitForExit(); + + _logger.Info("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds); + //_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray())); + return lines; + } + } + + private async Task StartReadingOutput(Stream source, List keyframes, CancellationToken cancellationToken) + { + try + { + using (var reader = new StreamReader(source)) + { + var text = await reader.ReadToEndAsync().ConfigureAwait(false); + + var lines = StringHelper.RegexSplit(text, "[\r\n]+"); + foreach (var line in lines) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + var values = line.Split('|') + .Where(i => !string.IsNullOrWhiteSpace(i)) + .Select(i => i.Split('=')) + .Where(i => i.Length == 2) + .ToDictionary(i => i[0], i => i[1]); + + string flags; + if (values.TryGetValue("flags", out flags) && string.Equals(flags, "k", StringComparison.OrdinalIgnoreCase)) + { + string pts_time; + double frameSeconds; + if (values.TryGetValue("pts_time", out pts_time) && double.TryParse(pts_time, NumberStyles.Any, CultureInfo.InvariantCulture, out frameSeconds)) + { + var ms = frameSeconds * 1000; + keyframes.Add(Convert.ToInt32(ms)); + } + } + } + } + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + _logger.ErrorException("Error reading ffprobe output", ex); + } + } /// /// The us culture /// -- cgit v1.2.3 From 6ea8ef9107275bfddf41bb88a10e913762f868d2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 12:48:42 -0500 Subject: restore changes --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 157 +--- .../MediaBrowser.ServerApplication.csproj | 805 +++++++++++++++++++-- MediaBrowser.sln | 4 + 3 files changed, 733 insertions(+), 233 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 1dc1a4215..be43079c5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -135,9 +135,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames); - var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile; - - return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval, + return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); } @@ -171,18 +169,16 @@ namespace MediaBrowser.MediaEncoding.Encoder /// The primary path. /// The protocol. /// if set to true [extract chapters]. - /// if set to true [extract key frame interval]. /// The probe size argument. /// if set to true [is audio]. /// Type of the video. /// The cancellation token. /// Task{MediaInfoResult}. - /// + /// ffprobe failed - streams and format are both null. private async Task GetMediaInfoInternal(string inputPath, string primaryPath, MediaProtocol protocol, bool extractChapters, - bool extractKeyFrameInterval, string probeSizeArgument, bool isAudio, VideoType videoType, @@ -274,31 +270,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) - { - if (ConfigurationManager.Configuration.EnableVideoFrameByFrameAnalysis && mediaInfo.Size.HasValue) - { - foreach (var stream in mediaInfo.MediaStreams) - { - if (EnableKeyframeExtraction(mediaInfo, stream)) - { - try - { - stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error getting key frame interval", ex); - } - } - } - } - } - return mediaInfo; } catch @@ -312,8 +283,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _ffProbeResourcePool.Release(); } } - - throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath)); } private async Task DetectInterlaced(MediaSourceInfo video, MediaStream videoStream, string inputPath, string probeSizeArgument) @@ -493,128 +462,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return 0; } - private bool EnableKeyframeExtraction(MediaSourceInfo mediaSource, MediaStream videoStream) - { - if (videoStream.Type == MediaStreamType.Video && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) && - !videoStream.IsInterlaced && - !(videoStream.IsAnamorphic ?? false)) - { - var audioStreams = mediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList(); - - // If it has aac audio then it will probably direct stream anyway, so don't bother with this - if (audioStreams.Count == 1 && string.Equals(audioStreams[0].Codec, "aac", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return true; - } - return false; - } - - private async Task> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken) - { - inputPath = inputPath.Split(new[] { ':' }, 2).Last().Trim('"'); - - const string args = "-show_packets -print_format compact -select_streams v:{1} -show_entries packet=flags -show_entries packet=pts_time \"{0}\""; - - var process = new Process - { - StartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - - // Must consume both or ffmpeg may hang due to deadlocks. See comments below. - RedirectStandardOutput = true, - RedirectStandardError = true, - FileName = FFProbePath, - Arguments = string.Format(args, inputPath, videoStreamIndex.ToString(CultureInfo.InvariantCulture)).Trim(), - - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }, - - EnableRaisingEvents = true - }; - - _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - - using (process) - { - var start = DateTime.UtcNow; - - process.Start(); - - var lines = new List(); - - try - { - process.BeginErrorReadLine(); - - await StartReadingOutput(process.StandardOutput.BaseStream, lines, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - if (cancellationToken.IsCancellationRequested) - { - throw; - } - } - - process.WaitForExit(); - - _logger.Info("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds); - //_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray())); - return lines; - } - } - - private async Task StartReadingOutput(Stream source, List keyframes, CancellationToken cancellationToken) - { - try - { - using (var reader = new StreamReader(source)) - { - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - - var lines = StringHelper.RegexSplit(text, "[\r\n]+"); - foreach (var line in lines) - { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - - var values = line.Split('|') - .Where(i => !string.IsNullOrWhiteSpace(i)) - .Select(i => i.Split('=')) - .Where(i => i.Length == 2) - .ToDictionary(i => i[0], i => i[1]); - - string flags; - if (values.TryGetValue("flags", out flags) && string.Equals(flags, "k", StringComparison.OrdinalIgnoreCase)) - { - string pts_time; - double frameSeconds; - if (values.TryGetValue("pts_time", out pts_time) && double.TryParse(pts_time, NumberStyles.Any, CultureInfo.InvariantCulture, out frameSeconds)) - { - var ms = frameSeconds * 1000; - keyframes.Add(Convert.ToInt32(ms)); - } - } - } - } - } - catch (OperationCanceledException) - { - throw; - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffprobe output", ex); - } - } /// /// The us culture /// diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 5813dcac5..382bb1c61 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -22,7 +22,7 @@ DEBUG;TRACE prompt 4 - true + false AnyCPU @@ -64,8 +64,9 @@ False ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll - - ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll + + False + ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll @@ -176,230 +177,878 @@ x86\SQLite.Interop.dll PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest diff --git a/MediaBrowser.sln b/MediaBrowser.sln index d0fbd743e..a9b5020ec 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Performance2.psess = Performance2.psess Performance3.psess = Performance3.psess Performance4.psess = Performance4.psess + Performance5.psess = Performance5.psess EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}" @@ -520,4 +521,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal -- cgit v1.2.3 From 8d6acbbc680299851192f7f68fae3cc07c87d3f8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 12:50:44 -0500 Subject: adjust logging --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index be43079c5..6f6f2b6a4 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -325,7 +325,7 @@ namespace MediaBrowser.MediaEncoding.Encoder EnableRaisingEvents = true }; - _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); + _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); var idetFoundInterlaced = false; using (var processWrapper = new ProcessWrapper(process, this, _logger)) -- cgit v1.2.3 From 4595c3854c397dd57a75db491c3d8f15acea1cc1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 13:02:32 -0500 Subject: update interlaced detection formats --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 6f6f2b6a4..9f23a305a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -295,7 +295,9 @@ namespace MediaBrowser.MediaEncoding.Encoder var formats = (video.Container ?? string.Empty).Split(',').ToList(); // Take a shortcut and limit this to containers that are likely to have interlaced content - if (!formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && + if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) { -- cgit v1.2.3 From 255747337a4b6017e35ce1b58192076bb3a90c61 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 13:23:13 -0500 Subject: fix merge conflict --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9f23a305a..f44d922d5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); - var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); + //var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); - if (videoStream != null) - { - var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); + //if (videoStream != null) + //{ + // var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); - if (isInterlaced) - { - videoStream.IsInterlaced = true; - } - } + // if (isInterlaced) + // { + // videoStream.IsInterlaced = true; + // } + //} return mediaInfo; } -- cgit v1.2.3 From 3c433e95b9ea8b0b19a1a1315ae19d1c7fca0e88 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 13:29:53 -0500 Subject: update interlaced detection --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f44d922d5..dedacccfa 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); - //var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); + var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); - //if (videoStream != null) - //{ - // var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); + if (videoStream != null) + { + var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false); - // if (isInterlaced) - // { - // videoStream.IsInterlaced = true; - // } - //} + if (isInterlaced) + { + videoStream.IsInterlaced = true; + } + } return mediaInfo; } @@ -294,14 +294,17 @@ namespace MediaBrowser.MediaEncoding.Encoder var formats = (video.Container ?? string.Empty).Split(',').ToList(); - // Take a shortcut and limit this to containers that are likely to have interlaced content - if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) + // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content + if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1) { - return false; + if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && + !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) + { + return false; + } } var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null"; -- cgit v1.2.3 From 59277211c7482e00a58cc74fc67068dab594d863 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 13:33:40 -0500 Subject: update interlaced detection --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index dedacccfa..f436ca3a0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -292,11 +292,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - var formats = (video.Container ?? string.Empty).Split(',').ToList(); - // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1) { + var formats = (video.Container ?? string.Empty).Split(',').ToList(); + if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && -- cgit v1.2.3 From fae4079a69eb253dd1f89b6925ca26f48be69eda Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 19 Dec 2015 23:37:59 -0500 Subject: restore changes --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index d9fda220d..c297a425d 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -876,7 +876,7 @@ namespace MediaBrowser.MediaEncoding.Probing } } - private void ExtractTimestamp(Model.MediaInfo.MediaInfo video) + private void ExtractTimestamp(MediaInfo video) { if (video.VideoType == VideoType.VideoFile) { diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 7c0929be6..ef62365c6 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -356,12 +356,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 2841eba20211c36c17d602e4cc2392bdcf0e33ad Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 24 Dec 2015 15:06:52 -0500 Subject: fixes #1310 - Downscaling 1280x720 to 720x404 --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 5 ++++- .../Encoder/EncodingJobFactory.cs | 5 ++++- MediaBrowser.Model/Dlna/ResolutionNormalizer.cs | 23 ++++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 7939a5976..9eb0f7d45 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1623,7 +1623,10 @@ namespace MediaBrowser.Api.Playback if (state.OutputVideoBitrate.HasValue) { - var resolution = ResolutionNormalizer.Normalize(state.OutputVideoBitrate.Value, + var resolution = ResolutionNormalizer.Normalize( + state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, + state.OutputVideoBitrate.Value, + state.VideoStream == null ? null : state.VideoStream.Codec, state.OutputVideoCodec, videoRequest.MaxWidth, videoRequest.MaxHeight); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index cf776b3f7..9cdc4a7bf 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -82,7 +82,10 @@ namespace MediaBrowser.MediaEncoding.Encoder if (state.OutputVideoBitrate.HasValue) { - var resolution = ResolutionNormalizer.Normalize(state.OutputVideoBitrate.Value, + var resolution = ResolutionNormalizer.Normalize( + state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, + state.OutputVideoBitrate.Value, + state.VideoStream == null ? null : state.VideoStream.Codec, state.OutputVideoCodec, request.MaxWidth, request.MaxHeight); diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs index b23c0b20b..8a412ac2c 100644 --- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs +++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs @@ -14,14 +14,29 @@ namespace MediaBrowser.Model.Dlna new ResolutionConfiguration(1280, 2500000) }; - public static ResolutionOptions Normalize(int maxBitrate, - string codec, + public static ResolutionOptions Normalize(int? inputBitrate, + int outputBitrate, + string inputCodec, + string outputCodec, int? maxWidth, int? maxHeight) { - foreach (var config in Configurations) + // If the bitrate isn't changing, then don't downlscale the resolution + if (inputBitrate.HasValue && outputBitrate >= inputBitrate.Value) + { + if (maxWidth.HasValue || maxHeight.HasValue) + { + return new ResolutionOptions + { + MaxWidth = maxWidth, + MaxHeight = maxHeight + }; + } + } + + foreach (var config in Configurations) { - if (maxBitrate <= config.MaxBitrate) + if (outputBitrate <= config.MaxBitrate) { var originvalValue = maxWidth; -- cgit v1.2.3 From c68a03b3abecc20977e948a749d3d6d37836aa21 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 26 Dec 2015 21:39:11 -0500 Subject: capture bit depth with ffprobe --- .../Probing/ProbeResultNormalizer.cs | 38 +++++----------------- 1 file changed, 9 insertions(+), 29 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index c297a425d..7c3293b89 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -159,6 +159,11 @@ namespace MediaBrowser.MediaEncoding.Probing } stream.ChannelLayout = ParseChannelLayout(streamInfo.channel_layout); + + if (streamInfo.bits_per_sample > 0) + { + stream.BitDepth = streamInfo.bits_per_sample; + } } else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase)) { @@ -177,7 +182,10 @@ namespace MediaBrowser.MediaEncoding.Probing stream.AverageFrameRate = GetFrameRate(streamInfo.avg_frame_rate); stream.RealFrameRate = GetFrameRate(streamInfo.r_frame_rate); - stream.BitDepth = GetBitDepth(stream.PixelFormat); + if (streamInfo.bits_per_sample > 0) + { + stream.BitDepth = streamInfo.bits_per_sample; + } //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || @@ -236,34 +244,6 @@ namespace MediaBrowser.MediaEncoding.Probing return stream; } - private int? GetBitDepth(string pixelFormat) - { - var eightBit = new List - { - "yuv420p", - "yuv411p", - "yuvj420p", - "uyyvyy411", - "nv12", - "nv21", - "rgb444le", - "rgb444be", - "bgr444le", - "bgr444be", - "yuvj411p" - }; - - if (!string.IsNullOrEmpty(pixelFormat)) - { - if (eightBit.Contains(pixelFormat, StringComparer.OrdinalIgnoreCase)) - { - return 8; - } - } - - return null; - } - /// /// Gets a string from an FFProbeResult tags dictionary /// -- cgit v1.2.3 From d59e4ff3577c95c372173cd68005abcc2baf217e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 27 Dec 2015 01:05:37 -0500 Subject: update bit depth probe --- MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs | 6 ++++++ MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 8 ++++++++ 2 files changed, 14 insertions(+) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs index 3e4bfe1a7..f32dd178f 100644 --- a/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs +++ b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs @@ -144,6 +144,12 @@ namespace MediaBrowser.MediaEncoding.Probing /// The bits_per_sample. public int bits_per_sample { get; set; } + /// + /// Gets or sets the bits_per_raw_sample. + /// + /// The bits_per_raw_sample. + public int bits_per_raw_sample { get; set; } + /// /// Gets or sets the r_frame_rate. /// diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 7c3293b89..791dc0cf1 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -164,6 +164,10 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.BitDepth = streamInfo.bits_per_sample; } + else if (streamInfo.bits_per_raw_sample > 0) + { + stream.BitDepth = streamInfo.bits_per_raw_sample; + } } else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase)) { @@ -186,6 +190,10 @@ namespace MediaBrowser.MediaEncoding.Probing { stream.BitDepth = streamInfo.bits_per_sample; } + else if (streamInfo.bits_per_raw_sample > 0) + { + stream.BitDepth = streamInfo.bits_per_raw_sample; + } //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) || // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) || -- cgit v1.2.3 From 6eb5d34af1d081b9e99928a42b2c2699d1d0116d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 27 Dec 2015 16:07:28 -0500 Subject: update subtitle encoder to allow format passthrough --- .../Subtitles/SubtitleEncoder.cs | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index ba44ed7dd..882b2e1c2 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -122,10 +122,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken) .ConfigureAwait(false); - using (var stream = subtitle.Item1) + var inputFormat = subtitle.Item2; + + if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase) && TryGetWriter(outputFormat) == null) { - var inputFormat = subtitle.Item2; + return subtitle.Item1; + } + using (var stream = subtitle.Item1) + { return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false); } } @@ -288,7 +293,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles return null; } - private ISubtitleWriter GetWriter(string format) + private ISubtitleWriter TryGetWriter(string format) { if (string.IsNullOrEmpty(format)) { @@ -312,6 +317,18 @@ namespace MediaBrowser.MediaEncoding.Subtitles return new TtmlWriter(); } + return null; + } + + private ISubtitleWriter GetWriter(string format) + { + var writer = TryGetWriter(format); + + if (writer != null) + { + return writer; + } + throw new ArgumentException("Unsupported format: " + format); } -- cgit v1.2.3 From ce59f19bc07eb73af133bfc2e8ee7e549d6d7566 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Jan 2016 12:05:30 -0500 Subject: separate artists with semi-colon --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 791dc0cf1..d98efffe7 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -455,7 +455,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrWhiteSpace(artists)) { - audio.Artists = SplitArtists(artists, new[] { '/' }, false) + audio.Artists = SplitArtists(artists, new[] { '/', ';' }, false) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); } -- cgit v1.2.3 From 81fb823c024a6652d967bb818cb4fe83417132c4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 11 Jan 2016 11:52:22 -0500 Subject: record mediastream comment --- .../MediaEncoding/IMediaEncoder.cs | 3 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 14 +++++----- .../Probing/ProbeResultNormalizer.cs | 1 + MediaBrowser.Model/Entities/MediaStream.cs | 6 ++++ .../MediaInfo/AudioImageProvider.cs | 29 ++++++++++++++------ .../Persistence/MediaStreamColumns.cs | 32 ++++++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 ++++++-- 7 files changed, 78 insertions(+), 18 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 427af6f6d..76ef054de 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding /// Extracts the audio image. /// /// The path. + /// Index of the image stream. /// The cancellation token. /// Task{Stream}. - Task ExtractAudioImage(string path, CancellationToken cancellationToken); + Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken); /// /// Extracts the video image. diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f436ca3a0..3c6a99c65 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -472,18 +472,18 @@ namespace MediaBrowser.MediaEncoding.Encoder /// protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public Task ExtractAudioImage(string path, CancellationToken cancellationToken) + public Task ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken) { - return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, 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) { - return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken); + return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken); } - private async Task ExtractImage(string[] inputFiles, 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; @@ -494,7 +494,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { try { - return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false); } catch (ArgumentException) { @@ -506,10 +506,10 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false); + return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false); } - private async Task ExtractImageInternal(string inputPath, 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)) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index d98efffe7..1df8896d5 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -141,6 +141,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (streamInfo.tags != null) { stream.Language = GetDictionaryValue(streamInfo.tags, "language"); + stream.Comment = GetDictionaryValue(streamInfo.tags, "comment"); } if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index d089f0aa9..7f4cc2f84 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities /// The language. public string Language { get; set; } + /// + /// Gets or sets the comment. + /// + /// The comment. + public string Comment { get; set; } + /// /// Gets or sets a value indicating whether this instance is interlaced. /// diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 8884412d2..c98a67bbd 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Extensions; +using System; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -43,20 +44,27 @@ namespace MediaBrowser.Providers.MediaInfo { var audio = (Audio)item; + var imageStreams = + audio.GetMediaSources(false) + .Take(1) + .SelectMany(i => i.MediaStreams) + .Where(i => i.Type == MediaStreamType.EmbeddedImage) + .ToList(); + // Can't extract if we didn't find a video stream in the file - if (!audio.GetMediaSources(false).Take(1).SelectMany(i => i.MediaStreams).Any(i => i.Type == MediaStreamType.EmbeddedImage)) + if (imageStreams.Count == 0) { return Task.FromResult(new DynamicImageResponse { HasImage = false }); } - return GetImage((Audio)item, cancellationToken); + return GetImage((Audio)item, imageStreams, cancellationToken); } - public async Task GetImage(Audio item, CancellationToken cancellationToken) + public async Task GetImage(Audio item, List imageStreams, CancellationToken cancellationToken) { var path = GetAudioImagePath(item); - if (!_fileSystem.FileExists(path)) + if (!_fileSystem.FileExists(path)) { var semaphore = GetLock(path); @@ -66,11 +74,16 @@ namespace MediaBrowser.Providers.MediaInfo try { // Check again in case it was saved while waiting for the lock - if (!_fileSystem.FileExists(path)) + if (!_fileSystem.FileExists(path)) { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + + var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? + imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1); + + var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index; - using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false)) + using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false)) { using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) { diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index c983dd547..7e46db5a7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -28,6 +28,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddKeyFramesColumn(); AddRefFramesCommand(); AddCodecTagColumn(); + AddCommentColumn(); + } + + private void AddCommentColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "Comment", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column Comment TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddCodecTagColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 1d3ac293e..3d5ddcf49 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -385,7 +385,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "IsAnamorphic", "RefFrames", "IsCabac", - "CodecTag" + "CodecTag", + "Comment" }; /// @@ -2683,6 +2684,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.IsCabac; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; + _saveStreamCommand.GetParameter(index++).Value = stream.Comment; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -2841,6 +2843,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.CodecTag = reader.GetString(26); } + if (!reader.IsDBNull(27)) + { + item.Comment = reader.GetString(27); + } + return item; } -- cgit v1.2.3 From 9f6fcc9e058848e5a07400ebca6c1357947b9336 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Jan 2016 15:49:33 -0500 Subject: capture conductor --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 10 +++++++++- MediaBrowser.Model/Entities/PersonType.cs | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 1df8896d5..31f6af181 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -441,7 +441,6 @@ namespace MediaBrowser.MediaEncoding.Probing } var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer"); - if (!string.IsNullOrWhiteSpace(composer)) { foreach (var person in Split(composer, false)) @@ -450,6 +449,15 @@ namespace MediaBrowser.MediaEncoding.Probing } } + var conductor = FFProbeHelpers.GetDictionaryValue(tags, "conductor"); + if (!string.IsNullOrWhiteSpace(conductor)) + { + foreach (var person in Split(conductor, false)) + { + audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Conductor }); + } + } + audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album"); var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists"); diff --git a/MediaBrowser.Model/Entities/PersonType.cs b/MediaBrowser.Model/Entities/PersonType.cs index ee80b1496..bdf846095 100644 --- a/MediaBrowser.Model/Entities/PersonType.cs +++ b/MediaBrowser.Model/Entities/PersonType.cs @@ -30,5 +30,9 @@ namespace MediaBrowser.Model.Entities /// The producer /// public const string Producer = "Producer"; + /// + /// The conductor + /// + public const string Conductor = "Conductor"; } } -- cgit v1.2.3 From 9b527dcd4fd95a886b7e6cd85a7c5b171f216b61 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Jan 2016 15:59:17 -0500 Subject: fix interlaced detection --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 3c6a99c65..ba0790bf3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -307,7 +307,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null"; + var args = "{0} -i {1} -map 0:v:{2} -an -filter:v idet -frames:v 500 -an -f null /dev/null"; var process = new Process { @@ -447,7 +447,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - if (((tff + bff) / total) >= .65) + if (((tff + bff) / total) >= .4) { return true; } @@ -490,7 +490,15 @@ namespace MediaBrowser.MediaEncoding.Encoder var inputArgument = GetInputArgument(inputFiles, protocol); - if (!isAudio) + if (isAudio) + { + if (imageStreamIndex.HasValue && imageStreamIndex.Value > 0) + { + // It seems for audio files we need to subtract 1 (for the audio stream??) + imageStreamIndex = imageStreamIndex.Value - 1; + } + } + else { try { @@ -543,9 +551,11 @@ 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} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) : - string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); + 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 probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol); -- cgit v1.2.3 From 0cd008bcb9e92e2dd74be58bf3566872ad8fb9ef Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Jan 2016 22:24:24 -0500 Subject: update commonio --- Emby.Drawing/Emby.Drawing.csproj | 2 +- Emby.Drawing/packages.config | 2 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 2 +- MediaBrowser.Api/packages.config | 2 +- .../MediaBrowser.Common.Implementations.csproj | 2 +- MediaBrowser.Common.Implementations/packages.config | 2 +- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Controller/packages.config | 2 +- MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 2 +- MediaBrowser.Dlna/packages.config | 2 +- MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj | 2 +- MediaBrowser.LocalMetadata/packages.config | 2 +- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 +- MediaBrowser.MediaEncoding/packages.config | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 2 +- MediaBrowser.Providers/packages.config | 2 +- .../MediaBrowser.Server.Implementations.csproj | 2 +- MediaBrowser.Server.Implementations/packages.config | 2 +- MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj | 2 +- MediaBrowser.Server.Mono/packages.config | 2 +- .../MediaBrowser.Server.Startup.Common.csproj | 2 +- MediaBrowser.Server.Startup.Common/packages.config | 2 +- MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj | 2 +- MediaBrowser.ServerApplication/packages.config | 2 +- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 2 +- MediaBrowser.WebDashboard/packages.config | 2 +- MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj | 2 +- MediaBrowser.XbmcMetadata/packages.config | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 6cda8b5d0..45ac97ecc 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -33,7 +33,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll False diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config index 3b8dbcab7..51731c474 100644 --- a/Emby.Drawing/packages.config +++ b/Emby.Drawing/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 08b99d5a4..7e55446ae 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -47,7 +47,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config index 258a097cd..83890e697 100644 --- a/MediaBrowser.Api/packages.config +++ b/MediaBrowser.Api/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index e87a6ad16..cb3a284c1 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -49,7 +49,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 84f663268..14f0f4719 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index a32ffdb3b..774e51bd3 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -46,7 +46,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config index 90b347929..8439bee10 100644 --- a/MediaBrowser.Controller/packages.config +++ b/MediaBrowser.Controller/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index db69a45c8..2d672ee87 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -42,7 +42,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll diff --git a/MediaBrowser.Dlna/packages.config b/MediaBrowser.Dlna/packages.config index 258a097cd..83890e697 100644 --- a/MediaBrowser.Dlna/packages.config +++ b/MediaBrowser.Dlna/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 5ef8eaaa3..c673c01df 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -33,7 +33,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.LocalMetadata/packages.config b/MediaBrowser.LocalMetadata/packages.config index fad6af08e..28556744d 100644 --- a/MediaBrowser.LocalMetadata/packages.config +++ b/MediaBrowser.LocalMetadata/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index df5ab4651..69f6186c7 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -41,7 +41,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll diff --git a/MediaBrowser.MediaEncoding/packages.config b/MediaBrowser.MediaEncoding/packages.config index e8a1767e3..d6a4fc90f 100644 --- a/MediaBrowser.MediaEncoding/packages.config +++ b/MediaBrowser.MediaEncoding/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 89bed8849..24397dd5a 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -50,7 +50,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll False diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config index 9002f1a40..08f8ef3b0 100644 --- a/MediaBrowser.Providers/packages.config +++ b/MediaBrowser.Providers/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index c5b6c1c42..e5c94a01b 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -43,7 +43,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index aac5951b5..5c04f2782 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index e9f631bf3..9f36599fa 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -54,7 +54,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll False diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config index 6a2a6c1e5..2956d69c6 100644 --- a/MediaBrowser.Server.Mono/packages.config +++ b/MediaBrowser.Server.Mono/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index b3865eadf..a4028d5b0 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -33,7 +33,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll False diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config index 6a2a6c1e5..2956d69c6 100644 --- a/MediaBrowser.Server.Startup.Common/packages.config +++ b/MediaBrowser.Server.Startup.Common/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index e8d5b6d27..3e62f4735 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -63,7 +63,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll False diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 3ea97a30e..db2bb5476 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 16f5ffeab..48a8bf253 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -49,7 +49,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index 24a8a5316..128a2f162 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,6 +1,6 @@  - + diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 353fe31ca..16b6ca995 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -33,7 +33,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.XbmcMetadata/packages.config b/MediaBrowser.XbmcMetadata/packages.config index fad6af08e..28556744d 100644 --- a/MediaBrowser.XbmcMetadata/packages.config +++ b/MediaBrowser.XbmcMetadata/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file -- cgit v1.2.3 From 51df0b79f208bf11be01488aa5ffd3b171ae2198 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 12:02:58 -0500 Subject: update interlaced detection --- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index ba0790bf3..2a3a416ad 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -292,16 +292,25 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content - if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1) + var formats = (video.Container ?? string.Empty).Split(',').ToList(); + var enableInterlacedDection = formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && + formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("wtv", StringComparer.OrdinalIgnoreCase); + + // If it's mpeg based, assume true + if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1) { - var formats = (video.Container ?? string.Empty).Split(',').ToList(); - - if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) + if (enableInterlacedDection) + { + return true; + } + } + else + { + // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content + if (!enableInterlacedDection) { return false; } -- cgit v1.2.3 From d1de9e01795d5984a52845817a63ec64e486218b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 4 Feb 2016 14:31:04 -0500 Subject: update sync encoding to match streaming --- MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs | 24 +-- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 211 ++++++++++++++------- .../Encoder/EncodingJobFactory.cs | 179 +++++++++-------- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 47 +++-- 4 files changed, 283 insertions(+), 178 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs index b488741d1..a4d4797eb 100644 --- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -19,38 +19,40 @@ namespace MediaBrowser.MediaEncoding.Encoder { } - protected override string GetCommandLineArguments(EncodingJob job) + protected override string GetCommandLineArguments(EncodingJob state) { var audioTranscodeParams = new List(); - var bitrate = job.OutputAudioBitrate; + var bitrate = state.OutputAudioBitrate; if (bitrate.HasValue) { audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(UsCulture)); } - if (job.OutputAudioChannels.HasValue) + if (state.OutputAudioChannels.HasValue) { - audioTranscodeParams.Add("-ac " + job.OutputAudioChannels.Value.ToString(UsCulture)); + audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture)); } - if (job.OutputAudioSampleRate.HasValue) + if (state.OutputAudioSampleRate.HasValue) { - audioTranscodeParams.Add("-ar " + job.OutputAudioSampleRate.Value.ToString(UsCulture)); + audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture)); } - var threads = GetNumberOfThreads(job, false); + const string vn = " -vn"; - var inputModifier = GetInputModifier(job); + var threads = GetNumberOfThreads(state, false); + + var inputModifier = GetInputModifier(state); return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"", inputModifier, - GetInputArgument(job), + GetInputArgument(state), threads, - " -vn", + vn, string.Join(" ", audioTranscodeParams.ToArray()), - job.OutputFilePath).Trim(); + state.OutputFilePath).Trim(); } protected override string GetOutputFileExtension(EncodingJob state) diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 98e4a58a6..3a4a12b35 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -303,15 +303,15 @@ namespace MediaBrowser.MediaEncoding.Encoder return job.Options.CpuCoreLimit ?? 0; } - protected string GetInputModifier(EncodingJob job, bool genPts = true) + protected string GetInputModifier(EncodingJob state, bool genPts = true) { var inputModifier = string.Empty; - var probeSize = GetProbeSizeArgument(job); + var probeSize = GetProbeSizeArgument(state); inputModifier += " " + probeSize; inputModifier = inputModifier.Trim(); - var userAgentParam = GetUserAgentParam(job); + var userAgentParam = GetUserAgentParam(state); if (!string.IsNullOrWhiteSpace(userAgentParam)) { @@ -320,35 +320,43 @@ namespace MediaBrowser.MediaEncoding.Encoder inputModifier = inputModifier.Trim(); - inputModifier += " " + GetFastSeekCommandLineParameter(job.Options); + inputModifier += " " + GetFastSeekCommandLineParameter(state.Options); inputModifier = inputModifier.Trim(); - if (job.IsVideoRequest && genPts) + if (state.IsVideoRequest && genPts) { inputModifier += " -fflags +genpts"; } - if (!string.IsNullOrEmpty(job.InputAudioSync)) + if (!string.IsNullOrEmpty(state.InputAudioSync)) { - inputModifier += " -async " + job.InputAudioSync; + inputModifier += " -async " + state.InputAudioSync; } - if (!string.IsNullOrEmpty(job.InputVideoSync)) + if (!string.IsNullOrEmpty(state.InputVideoSync)) { - inputModifier += " -vsync " + job.InputVideoSync; + inputModifier += " -vsync " + state.InputVideoSync; } - if (job.ReadInputAtNativeFramerate) + if (state.ReadInputAtNativeFramerate) { inputModifier += " -re"; } - var videoDecoder = GetVideoDecoder(job); + var videoDecoder = GetVideoDecoder(state); if (!string.IsNullOrWhiteSpace(videoDecoder)) { inputModifier += " " + videoDecoder; } + //if (state.IsVideoRequest) + //{ + // if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase)) + // { + // //inputModifier += " -noaccurate_seek"; + // } + //} + return inputModifier; } @@ -392,11 +400,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return null; } - private string GetUserAgentParam(EncodingJob job) + private string GetUserAgentParam(EncodingJob state) { string useragent = null; - job.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent); + state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent); if (!string.IsNullOrWhiteSpace(useragent)) { @@ -409,31 +417,31 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Gets the probe size argument. /// - /// The job. + /// The state. /// System.String. - private string GetProbeSizeArgument(EncodingJob job) + private string GetProbeSizeArgument(EncodingJob state) { - if (job.PlayableStreamFileNames.Count > 0) + if (state.PlayableStreamFileNames.Count > 0) { - return MediaEncoder.GetProbeSizeArgument(job.PlayableStreamFileNames.ToArray(), job.InputProtocol); + return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol); } - return MediaEncoder.GetProbeSizeArgument(new[] { job.MediaPath }, job.InputProtocol); + return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol); } /// /// Gets the fast seek command line parameter. /// - /// The options. + /// The request. /// System.String. /// The fast seek command line parameter. - protected string GetFastSeekCommandLineParameter(EncodingJobOptions options) + protected string GetFastSeekCommandLineParameter(EncodingJobOptions request) { - var time = options.StartTimeTicks; + var time = request.StartTimeTicks ?? 0; - if (time.HasValue && time.Value > 0) + if (time > 0) { - return string.Format("-ss {0}", MediaEncoder.GetTimeParameter(time.Value)); + return string.Format("-ss {0}", MediaEncoder.GetTimeParameter(time)); } return string.Empty; @@ -442,34 +450,35 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Gets the input argument. /// - /// The job. + /// The state. /// System.String. - protected string GetInputArgument(EncodingJob job) + protected string GetInputArgument(EncodingJob state) { - var arg = "-i " + GetInputPathArgument(job); + var arg = string.Format("-i {0}", GetInputPathArgument(state)); - if (job.SubtitleStream != null) + if (state.SubtitleStream != null) { - if (job.SubtitleStream.IsExternal && !job.SubtitleStream.IsTextSubtitleStream) + if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) { - arg += " -i \"" + job.SubtitleStream.Path + "\""; + arg += " -i \"" + state.SubtitleStream.Path + "\""; } } - return arg; + return arg.Trim(); } - private string GetInputPathArgument(EncodingJob job) + private string GetInputPathArgument(EncodingJob state) { - var protocol = job.InputProtocol; + var protocol = state.InputProtocol; + var mediaPath = state.MediaPath ?? string.Empty; - var inputPath = new[] { job.MediaPath }; + var inputPath = new[] { mediaPath }; - if (job.IsInputVideo) + if (state.IsInputVideo) { - if (!(job.VideoType == VideoType.Iso && job.IsoMount == null)) + if (!(state.VideoType == VideoType.Iso && state.IsoMount == null)) { - inputPath = MediaEncoderHelpers.GetInputArgument(FileSystem, job.MediaPath, job.InputProtocol, job.IsoMount, job.PlayableStreamFileNames); + inputPath = MediaEncoderHelpers.GetInputArgument(FileSystem, mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames); } } @@ -491,7 +500,7 @@ namespace MediaBrowser.MediaEncoding.Encoder }, false, cancellationToken).ConfigureAwait(false); - AttachMediaStreamInfo(state, liveStreamResponse.MediaSource, state.Options); + AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.Options); if (state.IsVideoRequest) { @@ -505,11 +514,11 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - private void AttachMediaStreamInfo(EncodingJob state, + private void AttachMediaSourceInfo(EncodingJob state, MediaSourceInfo mediaSource, EncodingJobOptions videoRequest) { - EncodingJobFactory.AttachMediaStreamInfo(state, mediaSource, videoRequest); + EncodingJobFactory.AttachMediaSourceInfo(state, mediaSource, videoRequest); } /// @@ -572,7 +581,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { param = "-preset superfast"; - param += " -crf 28"; + param += " -crf 23"; } else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) @@ -582,6 +591,19 @@ namespace MediaBrowser.MediaEncoding.Encoder param += " -crf 28"; } + // h264 (h264_qsv) + else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + param = "-preset 7 -look_ahead 0"; + + } + + // h264 (libnvenc) + else if (string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase)) + { + param = "-preset high-performance"; + } + // webm else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { @@ -644,9 +666,53 @@ namespace MediaBrowser.MediaEncoding.Encoder param += " -profile:v " + state.Options.Profile; } - if (state.Options.Level.HasValue) + var levelString = state.Options.Level.HasValue ? state.Options.Level.Value.ToString(CultureInfo.InvariantCulture) : null; + + if (!string.IsNullOrEmpty(levelString)) { - param += " -level " + state.Options.Level.Value.ToString(UsCulture); + 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)) + { + switch (levelString) + { + case "30": + param += " -level 3"; + break; + case "31": + param += " -level 3.1"; + break; + case "32": + param += " -level 3.2"; + break; + case "40": + param += " -level 4"; + break; + case "41": + param += " -level 4.1"; + break; + case "42": + param += " -level 4.2"; + break; + case "50": + param += " -level 5"; + break; + case "51": + param += " -level 5.1"; + break; + case "52": + param += " -level 5.2"; + break; + default: + param += " -level " + levelString; + break; + } + } + else + { + param += " -level " + levelString; + } } return "-pix_fmt yuv420p " + param; @@ -658,15 +724,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (bitrate.HasValue) { - var hasFixedResolution = state.Options.HasFixedResolution; - if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { - if (hasFixedResolution) - { - return string.Format(" -minrate:v ({0}*.90) -maxrate:v ({0}*1.10) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture)); - } - // With vpx when crf is used, b:v becomes a max rate // https://trac.ffmpeg.org/wiki/vpxEncodingGuide. But higher bitrate source files -b:v causes judder so limite the bitrate but dont allow it to "saturate" the bitrate. So dont contrain it down just up. return string.Format(" -maxrate:v {0} -bufsize:v ({0}*2) -b:v {0}", bitrate.Value.ToString(UsCulture)); @@ -677,20 +736,15 @@ namespace MediaBrowser.MediaEncoding.Encoder return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } - // H264 - if (hasFixedResolution) + // h264 + if (isHls) { - if (isHls) - { - return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } - return string.Format(" -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } return string.Empty; @@ -698,20 +752,23 @@ namespace MediaBrowser.MediaEncoding.Encoder protected double? GetFramerateParam(EncodingJob state) { - if (state.Options.Framerate.HasValue) + if (state.Options != null) { - return state.Options.Framerate.Value; - } - - var maxrate = state.Options.MaxFramerate; + if (state.Options.Framerate.HasValue) + { + return state.Options.Framerate.Value; + } - if (maxrate.HasValue && state.VideoStream != null) - { - var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate; + var maxrate = state.Options.MaxFramerate; - if (contentRate.HasValue && contentRate.Value > maxrate.Value) + if (maxrate.HasValue && state.VideoStream != null) { - return maxrate; + var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate; + + if (contentRate.HasValue && contentRate.Value > maxrate.Value) + { + return maxrate; + } } } @@ -852,7 +909,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); - filters.Add(string.Format("scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam)); + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam)); } // If a max height was requested @@ -863,6 +920,14 @@ namespace MediaBrowser.MediaEncoding.Encoder 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) @@ -917,8 +982,10 @@ namespace MediaBrowser.MediaEncoding.Encoder seconds.ToString(UsCulture)); } + var mediaPath = state.MediaPath ?? string.Empty; + return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB", - MediaEncoder.EscapeSubtitleFilterPath(state.MediaPath), + MediaEncoder.EscapeSubtitleFilterPath(mediaPath), state.InternalSubtitleStreamOffset.ToString(UsCulture), seconds.ToString(UsCulture)); } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 9cdc4a7bf..27072efe1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -66,38 +67,56 @@ namespace MediaBrowser.MediaEncoding.Encoder ? mediaSources.First() : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId)); - AttachMediaStreamInfo(state, mediaSource, options); + var videoRequest = state.Options; - state.OutputAudioBitrate = GetAudioBitrateParam(request, state.AudioStream); + AttachMediaSourceInfo(state, mediaSource, videoRequest); + + //var container = Path.GetExtension(state.RequestedUrl); + + //if (string.IsNullOrEmpty(container)) + //{ + // container = request.Static ? + // state.InputContainer : + // (Path.GetExtension(GetOutputFilePath(state)) ?? string.Empty).TrimStart('.'); + //} + + //state.OutputContainer = (container ?? string.Empty).TrimStart('.'); + + state.OutputAudioBitrate = GetAudioBitrateParam(state.Options, state.AudioStream); state.OutputAudioSampleRate = request.AudioSampleRate; - state.OutputAudioCodec = GetAudioCodec(request); + state.OutputAudioCodec = state.Options.AudioCodec; - state.OutputAudioChannels = GetNumAudioChannelsParam(request, state.AudioStream, state.OutputAudioCodec); + state.OutputAudioChannels = GetNumAudioChannelsParam(state.Options, state.AudioStream, state.OutputAudioCodec); - if (isVideoRequest) + if (videoRequest != null) { - state.OutputVideoCodec = GetVideoCodec(request); - state.OutputVideoBitrate = GetVideoBitrateParamValue(request, state.VideoStream); + state.OutputVideoCodec = state.Options.VideoCodec; + state.OutputVideoBitrate = GetVideoBitrateParamValue(state.Options, state.VideoStream); if (state.OutputVideoBitrate.HasValue) { var resolution = ResolutionNormalizer.Normalize( - state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, - state.OutputVideoBitrate.Value, - state.VideoStream == null ? null : state.VideoStream.Codec, + state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, + state.OutputVideoBitrate.Value, + state.VideoStream == null ? null : state.VideoStream.Codec, state.OutputVideoCodec, - request.MaxWidth, - request.MaxHeight); + videoRequest.MaxWidth, + videoRequest.MaxHeight); - request.MaxWidth = resolution.MaxWidth; - request.MaxHeight = resolution.MaxHeight; + videoRequest.MaxWidth = resolution.MaxWidth; + videoRequest.MaxHeight = resolution.MaxHeight; } } ApplyDeviceProfileSettings(state); - TryStreamCopy(state, request); + if (videoRequest != null) + { + TryStreamCopy(state, videoRequest); + } + + //state.OutputFilePath = GetOutputFilePath(state); return state; } @@ -119,7 +138,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - internal static void AttachMediaStreamInfo(EncodingJob state, + internal static void AttachMediaSourceInfo(EncodingJob state, MediaSourceInfo mediaSource, EncodingJobOptions videoRequest) { @@ -131,11 +150,6 @@ namespace MediaBrowser.MediaEncoding.Encoder state.RunTimeTicks = mediaSource.RunTimeTicks; state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; - if (mediaSource.ReadAtNativeFramerate) - { - state.ReadInputAtNativeFramerate = true; - } - if (mediaSource.VideoType.HasValue) { state.VideoType = mediaSource.VideoType.Value; @@ -156,6 +170,7 @@ namespace MediaBrowser.MediaEncoding.Encoder state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; state.InputBitrate = mediaSource.Bitrate; state.InputFileSize = mediaSource.Size; + state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate; if (state.ReadInputAtNativeFramerate || mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase)) @@ -165,6 +180,12 @@ namespace MediaBrowser.MediaEncoding.Encoder state.InputAudioSync = "1"; } + if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase)) + { + // Seeing some stuttering when transcoding wma to audio-only HLS + state.InputAudioSync = "1"; + } + var mediaStreams = mediaSource.MediaStreams; if (videoRequest != null) @@ -210,19 +231,21 @@ namespace MediaBrowser.MediaEncoding.Encoder /// System.Nullable{VideoCodecs}. private static string InferVideoCodec(string container) { - if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) + var ext = "." + (container ?? string.Empty); + + if (string.Equals(ext, ".asf", StringComparison.OrdinalIgnoreCase)) { return "wmv"; } - if (string.Equals(container, "webm", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vpx"; } - if (string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "theora"; } - if (string.Equals(container, "m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".m3u8", StringComparison.OrdinalIgnoreCase) || string.Equals(ext, ".ts", StringComparison.OrdinalIgnoreCase)) { return "h264"; } @@ -232,35 +255,37 @@ namespace MediaBrowser.MediaEncoding.Encoder private string InferAudioCodec(string container) { - if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase)) + var ext = "." + (container ?? string.Empty); + + if (string.Equals(ext, ".mp3", StringComparison.OrdinalIgnoreCase)) { return "mp3"; } - if (string.Equals(container, "aac", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".aac", StringComparison.OrdinalIgnoreCase)) { return "aac"; } - if (string.Equals(container, "wma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".wma", StringComparison.OrdinalIgnoreCase)) { return "wma"; } - if (string.Equals(container, "ogg", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogg", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "oga", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".oga", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "ogv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".ogv", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "webm", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webm", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } - if (string.Equals(container, "webma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(ext, ".webma", StringComparison.OrdinalIgnoreCase)) { return "vorbis"; } @@ -398,15 +423,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (bitrate.HasValue) { - var hasFixedResolution = state.Options.HasFixedResolution; - if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) { - if (hasFixedResolution) - { - return string.Format(" -minrate:v ({0}*.90) -maxrate:v ({0}*1.10) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture)); - } - // With vpx when crf is used, b:v becomes a max rate // https://trac.ffmpeg.org/wiki/vpxEncodingGuide. But higher bitrate source files -b:v causes judder so limite the bitrate but dont allow it to "saturate" the bitrate. So dont contrain it down just up. return string.Format(" -maxrate:v {0} -bufsize:v ({0}*2) -b:v {0}", bitrate.Value.ToString(UsCulture)); @@ -417,20 +435,15 @@ namespace MediaBrowser.MediaEncoding.Encoder return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } - // H264 - if (hasFixedResolution) + // h264 + if (isHls) { - if (isHls) - { - return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } - return string.Format(" -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); + return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); } return string.Empty; @@ -466,11 +479,11 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// Gets the name of the output audio codec /// - /// The request. + /// The state. /// System.String. - private string GetAudioCodec(EncodingJobOptions request) + internal static string GetAudioEncoder(EncodingJob state) { - var codec = request.AudioCodec; + var codec = state.OutputAudioCodec; if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase)) { @@ -489,40 +502,56 @@ namespace MediaBrowser.MediaEncoding.Encoder return "wmav2"; } - return (codec ?? string.Empty).ToLower(); + return codec.ToLower(); } /// /// Gets the name of the output video codec /// - /// The request. + /// The state. + /// The options. /// System.String. - private string GetVideoCodec(EncodingJobOptions request) + internal static string GetVideoEncoder(EncodingJob state, EncodingOptions options) { - var codec = request.VideoCodec; + var codec = state.OutputVideoCodec; - if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(codec)) { - return "libx264"; - } - if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) - { - return "libx265"; - } - if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) - { - return "libvpx"; - } - if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) - { - return "wmv2"; + if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) + { + return GetH264Encoder(state, options); + } + if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase)) + { + return "libvpx"; + } + if (string.Equals(codec, "wmv", StringComparison.OrdinalIgnoreCase)) + { + return "wmv2"; + } + if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) + { + return "libtheora"; + } + + return codec.ToLower(); } - if (string.Equals(codec, "theora", StringComparison.OrdinalIgnoreCase)) + + return "copy"; + } + + internal static string GetH264Encoder(EncodingJob state, EncodingOptions options) + { + if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - return "libtheora"; + // It's currently failing on live tv + if (state.RunTimeTicks.HasValue) + { + return "h264_qsv"; + } } - return (codec ?? string.Empty).ToLower(); + return "libx264"; } internal static bool CanStreamCopyVideo(EncodingJobOptions request, MediaStream videoStream) diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 127145aec..9d051b38b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -21,14 +21,14 @@ namespace MediaBrowser.MediaEncoding.Encoder protected override string GetCommandLineArguments(EncodingJob state) { // Get the output codec name - var videoCodec = state.OutputVideoCodec; + var videoCodec = EncodingJobFactory.GetVideoEncoder(state, GetEncodingOptions()); var format = string.Empty; var keyFrame = string.Empty; - if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase) && - state.Options.Context == EncodingContext.Streaming) + if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase)) { + // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js format = " -f mp4 -movflags frag_keyframe+empty_moov"; } @@ -53,42 +53,49 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets video arguments to pass to ffmpeg /// /// The state. - /// The video codec. + /// The video codec. /// System.String. - private string GetVideoArguments(EncodingJob state, string codec) + private string GetVideoArguments(EncodingJob state, string videoCodec) { - var args = "-codec:v:0 " + codec; + var args = "-codec:v:0 " + videoCodec; if (state.EnableMpegtsM2TsMode) { args += " -mpegts_m2ts_mode 1"; } - // See if we can save come cpu cycles by avoiding encoding - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) + var isOutputMkv = string.Equals(state.Options.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); + + if (state.RunTimeTicks.HasValue) { - return state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) ? - args + " -bsf:v h264_mp4toannexb" : - args; + //args += " -copyts -avoid_negative_ts disabled -start_at_zero"; } - if (state.Options.Context == EncodingContext.Streaming) + if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", - 5.ToString(UsCulture)); + if (state.VideoStream != null && IsH264(state.VideoStream) && + (string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + { + args += " -bsf:v h264_mp4toannexb"; + } - args += keyFrameArg; + return args; } + var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", + 5.ToString(UsCulture)); + + args += keyFrameArg; + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; // Add resolution params, if specified if (!hasGraphicalSubs) { - args += GetOutputSizeParam(state, codec); + args += GetOutputSizeParam(state, videoCodec); } - var qualityParam = GetVideoQualityParam(state, codec, false); + var qualityParam = GetVideoQualityParam(state, videoCodec, false); if (!string.IsNullOrEmpty(qualityParam)) { @@ -98,7 +105,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // This is for internal graphical subs if (hasGraphicalSubs) { - args += GetGraphicalSubtitleParam(state, codec); + args += GetGraphicalSubtitleParam(state, videoCodec); } return args; @@ -118,11 +125,11 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Get the output codec name - var codec = state.OutputAudioCodec; + var codec = EncodingJobFactory.GetAudioEncoder(state); var args = "-codec:a:0 " + codec; - if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { return args; } -- cgit v1.2.3 From bc6c0bd0b7ec6f57651c21726f66f9cf7a69cba3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 6 Feb 2016 16:36:29 -0500 Subject: update sync conversion --- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 9d051b38b..79f248468 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -26,7 +26,8 @@ namespace MediaBrowser.MediaEncoding.Encoder var format = string.Empty; var keyFrame = string.Empty; - if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase) && + state.Options.Context == EncodingContext.Streaming) { // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js format = " -f mp4 -movflags frag_keyframe+empty_moov"; -- cgit v1.2.3 From fcd15da1e6fb6e940f55c2def0e00554feae36e0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 7 Feb 2016 16:48:08 -0500 Subject: update progressive encoding --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 18 ++++++------------ MediaBrowser.Api/Playback/Dash/MpegDashService.cs | 2 +- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 2 +- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 18 ++++++------------ MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 2 +- 7 files changed, 17 insertions(+), 29 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bb7f6bb1e..bae8074fd 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -305,9 +305,8 @@ namespace MediaBrowser.Api.Playback /// /// The state. /// The video codec. - /// if set to true [is HLS]. /// System.String. - protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls) + protected string GetVideoQualityParam(StreamState state, string videoCodec) { var param = string.Empty; @@ -385,7 +384,7 @@ namespace MediaBrowser.Api.Playback param = "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec, isHls); + param += GetVideoBitrateParam(state, videoCodec); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -1190,7 +1189,7 @@ namespace MediaBrowser.Api.Playback return bitrate; } - protected string GetVideoBitrateParam(StreamState state, string videoCodec, bool isHls) + protected string GetVideoBitrateParam(StreamState state, string videoCodec) { var bitrate = state.OutputVideoBitrate; @@ -1209,14 +1208,9 @@ namespace MediaBrowser.Api.Playback } // h264 - if (isHls) - { - return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } return string.Empty; diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs index 9ec16fcc7..defb2eef0 100644 --- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs @@ -430,7 +430,7 @@ namespace MediaBrowser.Api.Playback.Dash var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; - args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg; + args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg; // Add resolution params, if specified if (!hasGraphicalSubs) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index baf662c34..4a83615b4 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -822,7 +822,7 @@ namespace MediaBrowser.Api.Playback.Hls var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; - args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg; + args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg; //args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0"; diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index be1db1a4d..22c38009a 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -106,7 +106,7 @@ namespace MediaBrowser.Api.Playback.Hls var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; - args += " " + GetVideoQualityParam(state, GetH264Encoder(state), true) + keyFrameArg; + args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg; // Add resolution params, if specified if (!hasGraphicalSubs) diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 19e568ec4..eaf65bd6b 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -166,7 +166,7 @@ namespace MediaBrowser.Api.Playback.Progressive args += GetOutputSizeParam(state, videoCodec); } - var qualityParam = GetVideoQualityParam(state, videoCodec, false); + var qualityParam = GetVideoQualityParam(state, videoCodec); if (!string.IsNullOrEmpty(qualityParam)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 3a4a12b35..4fabed850 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -568,9 +568,8 @@ namespace MediaBrowser.MediaEncoding.Encoder /// /// The state. /// The video codec. - /// if set to true [is HLS]. /// System.String. - protected string GetVideoQualityParam(EncodingJob state, string videoCodec, bool isHls) + protected string GetVideoQualityParam(EncodingJob state, string videoCodec) { var param = string.Empty; @@ -648,7 +647,7 @@ namespace MediaBrowser.MediaEncoding.Encoder param = "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec, isHls); + param += GetVideoBitrateParam(state, videoCodec); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -718,7 +717,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return "-pix_fmt yuv420p " + param; } - protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls) + protected string GetVideoBitrateParam(EncodingJob state, string videoCodec) { var bitrate = state.OutputVideoBitrate; @@ -737,14 +736,9 @@ namespace MediaBrowser.MediaEncoding.Encoder } // h264 - if (isHls) - { - return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } return string.Empty; diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 79f248468..5756566fe 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -96,7 +96,7 @@ namespace MediaBrowser.MediaEncoding.Encoder args += GetOutputSizeParam(state, videoCodec); } - var qualityParam = GetVideoQualityParam(state, videoCodec, false); + var qualityParam = GetVideoQualityParam(state, videoCodec); if (!string.IsNullOrEmpty(qualityParam)) { -- cgit v1.2.3 From e037fcbdafc3d93cd6daea37e93c68b69056d0c5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 9 Feb 2016 20:36:27 -0500 Subject: update sync encoding --- .../Encoder/EncodingJobFactory.cs | 25 +++++++++------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 27072efe1..252386af0 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -355,8 +355,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private int? GetNumAudioChannelsParam(EncodingJobOptions request, MediaStream audioStream, string outputAudioCodec) { var inputChannels = audioStream == null - ? null - : audioStream.Channels; + ? null + : audioStream.Channels; if (inputChannels <= 0) { @@ -373,15 +373,15 @@ namespace MediaBrowser.MediaEncoding.Encoder if (request.MaxAudioChannels.HasValue) { + var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1 + ? 2 + : 6; + if (inputChannels.HasValue) { - return Math.Min(request.MaxAudioChannels.Value, inputChannels.Value); + channelLimit = Math.Min(channelLimit, inputChannels.Value); } - var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1 - ? 2 - : 6; - // If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels return Math.Min(request.MaxAudioChannels.Value, channelLimit); } @@ -436,14 +436,9 @@ namespace MediaBrowser.MediaEncoding.Encoder } // h264 - if (isHls) - { - return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", - bitrate.Value.ToString(UsCulture), - (bitrate.Value * 2).ToString(UsCulture)); - } - - return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); + return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}", + bitrate.Value.ToString(UsCulture), + (bitrate.Value * 2).ToString(UsCulture)); } return string.Empty; -- cgit v1.2.3 From 1a2867ea5516989c993e0f01322142d532e6ebc4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 11 Feb 2016 14:11:28 -0500 Subject: support tagging 3d as mvc --- MediaBrowser.Controller/Providers/BaseItemXmlParser.cs | 4 ++++ MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs | 3 +++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 ++ MediaBrowser.Model/Entities/Video3DFormat.cs | 3 ++- .../Library/Resolvers/BaseVideoResolver.cs | 4 ++++ MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 4 ++++ MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 3 +++ 7 files changed, 22 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.MediaEncoding') diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 3e5353812..f9060d184 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -889,6 +889,10 @@ namespace MediaBrowser.Controller.Providers { video.Video3DFormat = Video3DFormat.FullSideBySide; } + else if (string.Equals("MVC", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.MVC; + } } break; } diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs index c9a4cb537..48c4fe2fd 100644 --- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs @@ -736,6 +736,9 @@ namespace MediaBrowser.LocalMetadata.Savers case Video3DFormat.HalfTopAndBottom: builder.Append("HTAB"); break; + case Video3DFormat.MVC: + builder.Append("MVC"); + break; } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 2a3a416ad..30e50fecd 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -557,6 +557,8 @@ namespace MediaBrowser.MediaEncoding.Encoder vf = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale=600:trunc(600/dar/2)*2"; // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made the scale width to 600 break; + default: + break; } } diff --git a/MediaBrowser.Model/Entities/Video3DFormat.cs b/MediaBrowser.Model/Entities/Video3DFormat.cs index 064b02edd..722df4281 100644 --- a/MediaBrowser.Model/Entities/Video3DFormat.cs +++ b/MediaBrowser.Model/Entities/Video3DFormat.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Entities HalfSideBySide, FullSideBySide, FullTopAndBottom, - HalfTopAndBottom + HalfTopAndBottom, + MVC } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 9ebf82c02..9edd3f83f 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -242,6 +242,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { video.Video3DFormat = Video3DFormat.HalfTopAndBottom; } + else if (string.Equals(format3D, "mvc", StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.MVC; + } } } diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 40b974ee7..30243ff57 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1173,6 +1173,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers { video.Video3DFormat = Video3DFormat.FullSideBySide; } + else if (string.Equals("MVC", val, StringComparison.OrdinalIgnoreCase)) + { + video.Video3DFormat = Video3DFormat.MVC; + } } break; } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index ec12088b3..53a7926ca 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -404,6 +404,9 @@ namespace MediaBrowser.XbmcMetadata.Savers case Video3DFormat.HalfTopAndBottom: writer.WriteElementString("format3d", "HTAB"); break; + case Video3DFormat.MVC: + writer.WriteElementString("format3d", "MVC"); + break; } } } -- cgit v1.2.3