From c5c8426c202c1385f661c5e0faab7d10f6340a7f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 2 Sep 2016 00:13:28 -0400 Subject: fixes #219 - [Bug] Missing hardware device reference in convert job with vaapi transcoding --- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs') diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 6bf414dfa..ce00acb52 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -481,6 +481,16 @@ namespace MediaBrowser.MediaEncoding.Encoder } } + if (state.IsVideoRequest) + { + var encodingOptions = GetEncodingOptions(); + var videoEncoder = EncodingJobFactory.GetVideoEncoder(MediaEncoder, state, encodingOptions); + if (videoEncoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) + { + arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + } + } + return arg.Trim(); } -- cgit v1.2.3 From 3a4b0ea018d8d7f09b464a6a114844a06b05a26c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 7 Sep 2016 22:55:54 -0400 Subject: limit transcoding to level 41 --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 67 +++++++++++++++-------- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 61 ++++++++++++++------- 2 files changed, 85 insertions(+), 43 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5d7f01ad3..7a40d5bd1 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -337,9 +337,9 @@ namespace MediaBrowser.Api.Playback /// Gets the video bitrate to specify on the command line /// /// The state. - /// The video codec. + /// The video codec. /// System.String. - protected string GetVideoQualityParam(StreamState state, string videoCodec) + protected string GetVideoQualityParam(StreamState state, string videoEncoder) { var param = string.Empty; @@ -348,7 +348,7 @@ namespace MediaBrowser.Api.Playback var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(encodingOptions.H264Preset)) { @@ -369,7 +369,7 @@ namespace MediaBrowser.Api.Playback } } - else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param += "-preset fast"; @@ -377,20 +377,20 @@ namespace MediaBrowser.Api.Playback } // h264 (h264_qsv) - else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { param += "-preset 7 -look_ahead 0"; } // h264 (h264_nvenc) - else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param += "-preset default"; } // webm - else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -417,23 +417,23 @@ namespace MediaBrowser.Api.Playback qmax); } - else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; } // asf/wmv - else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) { param += "-qmin 2"; } - else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { param += "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec); + param += GetVideoBitrateParam(state, videoEncoder); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -448,8 +448,8 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.VideoRequest.Profile; @@ -458,11 +458,13 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.VideoRequest.Level)) { + var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level); + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { - switch (state.VideoRequest.Level) + switch (level) { case "30": param += " -level 3"; @@ -492,20 +494,20 @@ namespace MediaBrowser.Api.Playback param += " -level 5.2"; break; default: - param += " -level " + state.VideoRequest.Level; + param += " -level " + level; break; } } - else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { - param += " -level " + state.VideoRequest.Level; + param += " -level " + level; } } - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -513,6 +515,25 @@ namespace MediaBrowser.Api.Playback return param; } + private string NormalizeTranscodingLevel(string videoCodec, string level) + { + double requestLevel; + + // Clients may direct play higher than level 41, but there's no reason to transcode higher + if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel)) + { + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + if (requestLevel > 41) + { + return "41"; + } + } + } + + return level; + } + protected string GetAudioFilterParam(StreamState state, bool isHls) { var volParam = string.Empty; diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index ce00acb52..2ded8a66f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -595,23 +595,23 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Gets the video bitrate to specify on the command line /// /// The state. - /// The video codec. + /// The video codec. /// System.String. - protected string GetVideoQualityParam(EncodingJob state, string videoCodec) + protected string GetVideoQualityParam(EncodingJob state, string videoEncoder) { var param = string.Empty; var isVc1 = state.VideoStream != null && string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase); - if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { param = "-preset superfast"; param += " -crf 23"; } - else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase)) { param = "-preset fast"; @@ -619,20 +619,20 @@ namespace MediaBrowser.MediaEncoding.Encoder } // h264 (h264_qsv) - else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { param = "-preset 7 -look_ahead 0"; } // h264 (h264_nvenc) - else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param = "-preset llhq"; } // webm - else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase)) { // Values 0-3, 0 being highest quality but slower var profileScore = 0; @@ -659,23 +659,23 @@ namespace MediaBrowser.MediaEncoding.Encoder qmax); } - else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase)) { param = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2"; } // asf/wmv - else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase)) { param = "-qmin 2"; } - else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { param = "-mbd 2"; } - param += GetVideoBitrateParam(state, videoCodec); + param += GetVideoBitrateParam(state, videoEncoder); var framerate = GetFramerateParam(state); if (framerate.HasValue) @@ -690,8 +690,8 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.Options.Profile)) { - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { // not supported by h264_omx param += " -profile:v " + state.Options.Profile; @@ -702,9 +702,11 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(levelString)) { + levelString = NormalizeTranscodingLevel(state.OutputVideoCodec, levelString); + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { switch (levelString) { @@ -740,16 +742,16 @@ namespace MediaBrowser.MediaEncoding.Encoder break; } } - else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase)) + else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { param += " -level " + levelString; } } - if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && - !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) && + !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) { param = "-pix_fmt yuv420p " + param; } @@ -757,6 +759,25 @@ namespace MediaBrowser.MediaEncoding.Encoder return param; } + private string NormalizeTranscodingLevel(string videoCodec, string level) + { + double requestLevel; + + // Clients may direct play higher than level 41, but there's no reason to transcode higher + if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel)) + { + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + if (requestLevel > 41) + { + return "41"; + } + } + } + + return level; + } + protected string GetVideoBitrateParam(EncodingJob state, string videoCodec) { var bitrate = state.OutputVideoBitrate; -- cgit v1.2.3 From 1cf6cfb11c6cc80ede364267e4b7cd49ad8bb688 Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Tue, 13 Sep 2016 18:29:53 +0200 Subject: fix graphical subtitle transcoding with vaapi --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 17 +++++++++++++++-- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 7a40d5bd1..4a62da6f6 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -767,7 +767,20 @@ namespace MediaBrowser.Api.Playback if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue) { outputSizeParam = GetOutputSizeParam(state, outputVideoCodec).TrimEnd('"'); - outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase)); + + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase)); + } + else + { + outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase)); + } + } + + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0) + { + outputSizeParam = ",format=nv12|vaapi,hwupload"; } var videoSizeParam = string.Empty; @@ -1022,7 +1035,7 @@ namespace MediaBrowser.Api.Playback var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); if (GetVideoEncoder(state).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) { - arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + arg = "-hwaccel vaapi -hwaccel_output_format yuv420p -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 2ded8a66f..9d8b7fd63 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -487,7 +487,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var videoEncoder = EncodingJobFactory.GetVideoEncoder(MediaEncoder, state, encodingOptions); if (videoEncoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) { - arg = "-hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + arg = "-hwaccel vaapi -hwaccel_output_format yuv420p -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; } } @@ -565,7 +565,20 @@ namespace MediaBrowser.MediaEncoding.Encoder { outputSizeParam = await GetOutputSizeParam(state, outputVideoCodec).ConfigureAwait(false); outputSizeParam = outputSizeParam.TrimEnd('"'); - outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase)); + + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase)) + { + outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("format", StringComparison.OrdinalIgnoreCase)); + } + else + { + outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase)); + } + } + + if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase) && outputSizeParam.Length == 0) + { + outputSizeParam = ",format=nv12|vaapi,hwupload"; } var videoSizeParam = string.Empty; -- cgit v1.2.3 From 3d260bd13c3e2ea21dd6ca0209e1c7b0f7cf1ae9 Mon Sep 17 00:00:00 2001 From: Jan Friedrich Date: Sat, 24 Sep 2016 17:34:54 +0200 Subject: vaapi: copy decoded frames to main memory only when necessary --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 10 +++++++++- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 371247ecd..fe9869664 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1037,7 +1037,15 @@ namespace MediaBrowser.Api.Playback var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); if (GetVideoEncoder(state).IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) { - arg = "-hwaccel vaapi -hwaccel_output_format yuv420p -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; + var hwOutputFormat = "vaapi"; + + if (hasGraphicalSubs) + { + hwOutputFormat = "yuv420p"; + } + + arg = "-hwaccel vaapi -hwaccel_output_format " + hwOutputFormat + " -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 9d8b7fd63..e8121d178 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -487,7 +487,15 @@ namespace MediaBrowser.MediaEncoding.Encoder var videoEncoder = EncodingJobFactory.GetVideoEncoder(MediaEncoder, state, encodingOptions); if (videoEncoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1) { - arg = "-hwaccel vaapi -hwaccel_output_format yuv420p -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.Options.SubtitleMethod == SubtitleDeliveryMethod.Encode; + var hwOutputFormat = "vaapi"; + + if (hasGraphicalSubs) + { + hwOutputFormat = "yuv420p"; + } + + arg = "-hwaccel vaapi -hwaccel_output_format " + hwOutputFormat + " -vaapi_device " + encodingOptions.VaapiDevice + " " + arg; } } -- cgit v1.2.3 From c4e137e6cf7a52937e1169d1f170da4b8e72ba6a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 4 Oct 2016 01:15:39 -0400 Subject: update timer listings --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 5 ++- MediaBrowser.Api/Playback/BaseStreamingService.cs | 10 +++-- MediaBrowser.Controller/LiveTv/TimerInfo.cs | 1 + MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 10 +++-- MediaBrowser.Model/Dto/BaseItemDto.cs | 1 + MediaBrowser.Model/LiveTv/TimerQuery.cs | 2 + .../LiveTv/EmbyTV/EmbyTV.cs | 44 ++++++++++++---------- .../LiveTv/EmbyTV/RecordingHelper.cs | 20 +++++----- .../LiveTv/LiveTvDtoService.cs | 1 + .../LiveTv/LiveTvManager.cs | 14 +++++++ 10 files changed, 71 insertions(+), 37 deletions(-) (limited to 'MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index ecc17374f..4baae031f 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -315,6 +315,8 @@ namespace MediaBrowser.Api.LiveTv public string SeriesTimerId { get; set; } public bool? IsActive { get; set; } + + public bool? IsScheduled { get; set; } } [Route("/LiveTv/Programs", "GET,POST", Summary = "Gets available live tv epgs..")] @@ -1095,7 +1097,8 @@ namespace MediaBrowser.Api.LiveTv { ChannelId = request.ChannelId, SeriesTimerId = request.SeriesTimerId, - IsActive = request.IsActive + IsActive = request.IsActive, + IsScheduled = request.IsScheduled }, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 7f41cb059..bcf3bd28e 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -463,13 +463,15 @@ namespace MediaBrowser.Api.Playback var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level); // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (level) { case "30": - param += " -level 3"; + param += " -level 3.0"; break; case "31": param += " -level 3.1"; @@ -478,7 +480,7 @@ namespace MediaBrowser.Api.Playback param += " -level 3.2"; break; case "40": - param += " -level 4"; + param += " -level 4.0"; break; case "41": param += " -level 4.1"; @@ -487,7 +489,7 @@ namespace MediaBrowser.Api.Playback param += " -level 4.2"; break; case "50": - param += " -level 5"; + param += " -level 5.0"; break; case "51": param += " -level 5.1"; diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index 978e9e1a8..fd614253a 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -106,6 +106,7 @@ namespace MediaBrowser.Controller.LiveTv public string EpisodeTitle { get; set; } public DateTime? OriginalAirDate { get; set; } public bool IsProgramSeries { get; set; } + public bool IsRepeat { get; set; } public string HomePageUrl { get; set; } public float? CommunityRating { get; set; } public string ShortOverview { get; set; } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index e8121d178..f1e2f7241 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -726,13 +726,15 @@ namespace MediaBrowser.MediaEncoding.Encoder levelString = NormalizeTranscodingLevel(state.OutputVideoCodec, levelString); // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (levelString) { case "30": - param += " -level 3"; + param += " -level 3.0"; break; case "31": param += " -level 3.1"; @@ -741,7 +743,7 @@ namespace MediaBrowser.MediaEncoding.Encoder param += " -level 3.2"; break; case "40": - param += " -level 4"; + param += " -level 4.0"; break; case "41": param += " -level 4.1"; @@ -750,7 +752,7 @@ namespace MediaBrowser.MediaEncoding.Encoder param += " -level 4.2"; break; case "50": - param += " -level 5"; + param += " -level 5.0"; break; case "51": param += " -level 5.1"; diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 9434ab03a..19853fd2b 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -1215,6 +1215,7 @@ namespace MediaBrowser.Model.Dto /// /// The timer identifier. public string TimerId { get; set; } + public RecordingStatus TimerStatus { get; set; } /// /// Gets or sets the current program. /// diff --git a/MediaBrowser.Model/LiveTv/TimerQuery.cs b/MediaBrowser.Model/LiveTv/TimerQuery.cs index 87b6b89ac..310dc486f 100644 --- a/MediaBrowser.Model/LiveTv/TimerQuery.cs +++ b/MediaBrowser.Model/LiveTv/TimerQuery.cs @@ -15,5 +15,7 @@ public string SeriesTimerId { get; set; } public bool? IsActive { get; set; } + + public bool? IsScheduled { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 4530bfcb6..a3ba2c6f8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -629,6 +629,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV existingTimer.IsNews = updatedTimer.IsNews; existingTimer.IsMovie = updatedTimer.IsMovie; existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries; + existingTimer.IsRepeat = updatedTimer.IsRepeat; existingTimer.IsSports = updatedTimer.IsSports; existingTimer.Name = updatedTimer.Name; existingTimer.OfficialRating = updatedTimer.OfficialRating; @@ -665,8 +666,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var excludeStatues = new List { - RecordingStatus.Completed, - RecordingStatus.Cancelled + RecordingStatus.Completed }; var timers = _timerProvider.GetAll() @@ -1591,6 +1591,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private bool ShouldCancelTimerForSeriesTimer(SeriesTimerInfo seriesTimer, TimerInfo timer) { + if (!seriesTimer.RecordAnyTime) + { + if (Math.Abs(seriesTimer.StartDate.TimeOfDay.Ticks - timer.StartDate.TimeOfDay.Ticks) >= TimeSpan.FromMinutes(5).Ticks) + { + return true; + } + + if (!seriesTimer.Days.Contains(timer.StartDate.ToLocalTime().DayOfWeek)) + { + return true; + } + } + + if (seriesTimer.RecordNewOnly && timer.IsRepeat) + { + return true; + } + + if (!seriesTimer.RecordAnyChannel && !string.Equals(timer.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + return seriesTimer.SkipEpisodesInLibrary && IsProgramAlreadyInLibrary(timer); } @@ -1734,23 +1757,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private IEnumerable GetProgramsForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms) { - if (!seriesTimer.RecordAnyTime) - { - allPrograms = allPrograms.Where(epg => Math.Abs(seriesTimer.StartDate.TimeOfDay.Ticks - epg.StartDate.TimeOfDay.Ticks) < TimeSpan.FromMinutes(5).Ticks); - - allPrograms = allPrograms.Where(i => seriesTimer.Days.Contains(i.StartDate.ToLocalTime().DayOfWeek)); - } - - if (seriesTimer.RecordNewOnly) - { - allPrograms = allPrograms.Where(epg => !epg.IsRepeat); - } - - if (!seriesTimer.RecordAnyChannel) - { - allPrograms = allPrograms.Where(epg => string.Equals(epg.ChannelId, seriesTimer.ChannelId, StringComparison.OrdinalIgnoreCase)); - } - if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId)) { _logger.Error("seriesTimer.SeriesId is null. Cannot find programs for series"); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs index bb6935e8e..f7b4b3fde 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.LiveTv; using System; using System.Globalization; +using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -12,24 +13,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds); } - public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo series) + public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo seriesTimer) { var timer = new TimerInfo(); timer.ChannelId = parent.ChannelId; - timer.Id = (series.Id + parent.Id).GetMD5().ToString("N"); + timer.Id = (seriesTimer.Id + parent.Id).GetMD5().ToString("N"); timer.StartDate = parent.StartDate; timer.EndDate = parent.EndDate; timer.ProgramId = parent.Id; - timer.PrePaddingSeconds = series.PrePaddingSeconds; - timer.PostPaddingSeconds = series.PostPaddingSeconds; - timer.IsPostPaddingRequired = series.IsPostPaddingRequired; - timer.IsPrePaddingRequired = series.IsPrePaddingRequired; - timer.KeepUntil = series.KeepUntil; - timer.Priority = series.Priority; + timer.PrePaddingSeconds = seriesTimer.PrePaddingSeconds; + timer.PostPaddingSeconds = seriesTimer.PostPaddingSeconds; + timer.IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired; + timer.IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired; + timer.KeepUntil = seriesTimer.KeepUntil; + timer.Priority = seriesTimer.Priority; timer.Name = parent.Name; timer.Overview = parent.Overview; - timer.SeriesTimerId = series.Id; + timer.SeriesTimerId = seriesTimer.Id; CopyProgramInfoToTimerInfo(parent, timer); @@ -53,6 +54,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV timerInfo.CommunityRating = programInfo.CommunityRating; timerInfo.ShortOverview = programInfo.ShortOverview; timerInfo.OfficialRating = programInfo.OfficialRating; + timerInfo.IsRepeat = programInfo.IsRepeat; } public static string GetRecordingName(TimerInfo info) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 348bcd97b..2189cf627 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -72,6 +72,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv dto.ProgramInfo = _dtoService.GetBaseItemDto(program, new DtoOptions()); dto.ProgramInfo.TimerId = dto.Id; + dto.ProgramInfo.SeriesTimerId = dto.SeriesTimerId; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index e34868428..84b162286 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1087,6 +1087,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id) .ToString("N"); + program.TimerStatus = timer.Status; + if (!string.IsNullOrEmpty(timer.SeriesTimerId)) { program.SeriesTimerId = _tvDtoService.GetInternalSeriesTimerId(serviceName, timer.SeriesTimerId) @@ -1875,6 +1877,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } + if (query.IsScheduled.HasValue) + { + if (query.IsScheduled.Value) + { + timers = timers.Where(i => i.Item1.Status == RecordingStatus.New || i.Item1.Status == RecordingStatus.Scheduled); + } + else + { + timers = timers.Where(i => !(i.Item1.Status == RecordingStatus.New || i.Item1.Status == RecordingStatus.Scheduled)); + } + } + if (!string.IsNullOrEmpty(query.ChannelId)) { var guid = new Guid(query.ChannelId); -- cgit v1.2.3