diff --git a/CHANGELOG.md b/CHANGELOG.md index d6edbf607..b5f7e3d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - This includes a new setting to force a particular vaapi driver (`iHD` or `i965`), as some Gen 8 or 9 hardware that is supported by both drivers will perform better with one or the other - Fix scanning and indexing local movies and episodes without NFO metadata - Fix displaying seasons for shows with no year (in metadata or in folder name) +- Fix "direct play" in MPEG-TS mode (copy audio and video stream when `Transcode` is unchecked) ## [0.0.58-alpha] - 2021-09-15 ### Added diff --git a/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs b/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs index 50a1870ad..748ba33d1 100644 --- a/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs +++ b/ErsatzTV.Application/FFmpegProfiles/Commands/UpdateFFmpegProfileHandler.cs @@ -37,17 +37,17 @@ namespace ErsatzTV.Application.FFmpegProfiles.Commands p.Transcode = update.Transcode; p.HardwareAcceleration = update.HardwareAcceleration; p.ResolutionId = update.ResolutionId; - p.NormalizeVideo = update.NormalizeVideo; + p.NormalizeVideo = update.Transcode && update.NormalizeVideo; p.VideoCodec = update.VideoCodec; p.VideoBitrate = update.VideoBitrate; p.VideoBufferSize = update.VideoBufferSize; p.AudioCodec = update.AudioCodec; p.AudioBitrate = update.AudioBitrate; p.AudioBufferSize = update.AudioBufferSize; - p.NormalizeLoudness = update.NormalizeLoudness; + p.NormalizeLoudness = update.Transcode && update.NormalizeLoudness; p.AudioChannels = update.AudioChannels; p.AudioSampleRate = update.AudioSampleRate; - p.NormalizeAudio = update.NormalizeAudio; + p.NormalizeAudio = update.Transcode && update.NormalizeAudio; await dbContext.SaveChangesAsync(); return new UpdateFFmpegProfileResult(p.Id); } diff --git a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs index a0da52630..dd5cafe5d 100644 --- a/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs +++ b/ErsatzTV.Core.Tests/FFmpeg/FFmpegPlaybackSettingsCalculatorTests.cs @@ -258,6 +258,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 } }; @@ -283,6 +284,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1280, Height = 720 } }; @@ -309,6 +311,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 } }; @@ -334,6 +337,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeVideo = false, Resolution = new Resolution { Width = 1920, Height = 1080 } }; @@ -359,6 +363,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoCodec = "testCodec" @@ -387,6 +392,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoCodec = "testCodec" @@ -416,6 +422,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoCodec = "testCodec" @@ -444,6 +451,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoCodec = "libx264" @@ -473,6 +481,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = false, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoCodec = "libx264" @@ -495,12 +504,47 @@ namespace ErsatzTV.Core.Tests.FFmpeg actual.PadToDesiredResolution.Should().BeFalse(); actual.VideoCodec.Should().Be("copy"); } + + [Test] + public void + Should_SetCopyVideoCodec_AndCopyAudioCodec_When_NotTranscoding_ForTransportStream() + { + var ffmpegProfile = new FFmpegProfile + { + Transcode = false, + NormalizeVideo = true, + NormalizeAudio = true, + NormalizeLoudness = true, + Resolution = new Resolution { Width = 1920, Height = 1080 }, + VideoCodec = "libx264" + }; + + // not anamorphic + var version = new MediaVersion + { Width = 1920, Height = 1080, SampleAspectRatio = "1:1" }; + + FFmpegPlaybackSettings actual = _calculator.CalculateSettings( + StreamingMode.TransportStream, + ffmpegProfile, + version, + new MediaStream { Codec = "mpeg2video" }, + new MediaStream(), + DateTimeOffset.Now, + DateTimeOffset.Now); + + actual.ScaledSize.IsNone.Should().BeTrue(); + actual.PadToDesiredResolution.Should().BeFalse(); + actual.VideoCodec.Should().Be("copy"); + actual.NormalizeLoudness.Should().BeFalse(); + actual.AudioCodec.Should().Be("copy"); + } [Test] public void Should_SetVideoBitrate_When_ContentIsPadded_ForTransportStream() { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoBitrate = 2525 @@ -528,6 +572,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoBitrate = 2525 @@ -556,6 +601,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoBufferSize = 2525 @@ -584,6 +630,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { var ffmpegProfile = new FFmpegProfile { + Transcode = true, NormalizeVideo = true, Resolution = new Resolution { Width = 1920, Height = 1080 }, VideoBufferSize = 2525 @@ -612,6 +659,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioCodec = "aac" }; @@ -658,6 +706,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioCodec = "aac" }; @@ -681,6 +730,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioCodec = "aac" }; @@ -704,6 +754,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioBitrate = 2424, AudioCodec = "ac3" @@ -728,6 +779,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioBufferSize = 2424, AudioCodec = "ac3" @@ -752,6 +804,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioCodec = "ac3", AudioChannels = 6 @@ -776,6 +829,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioCodec = "ac3", AudioSampleRate = 48 @@ -800,6 +854,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioChannels = 6 }; @@ -823,6 +878,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioSampleRate = 48 }; @@ -846,6 +902,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, AudioSampleRate = 48, AudioCodec = "ac3" @@ -870,6 +927,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = true, NormalizeLoudness = true }; @@ -893,6 +951,7 @@ namespace ErsatzTV.Core.Tests.FFmpeg { FFmpegProfile ffmpegProfile = TestProfile() with { + Transcode = true, NormalizeAudio = false, NormalizeLoudness = true }; diff --git a/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs b/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs index 070bc0ccb..c285cb3d5 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegPlaybackSettingsCalculator.cs @@ -85,12 +85,12 @@ namespace ErsatzTV.Core.FFmpeg } IDisplaySize sizeAfterScaling = result.ScaledSize.IfNone(version); - if (ffmpegProfile.NormalizeVideo && !sizeAfterScaling.IsSameSizeAs(ffmpegProfile.Resolution)) + if (ffmpegProfile.Transcode && ffmpegProfile.NormalizeVideo && !sizeAfterScaling.IsSameSizeAs(ffmpegProfile.Resolution)) { result.PadToDesiredResolution = true; } - if (ffmpegProfile.NormalizeVideo) + if (ffmpegProfile.Transcode && ffmpegProfile.NormalizeVideo) { result.VideoTrackTimeScale = 90000; } @@ -107,7 +107,7 @@ namespace ErsatzTV.Core.FFmpeg result.VideoCodec = "copy"; } - if (ffmpegProfile.NormalizeAudio) + if (ffmpegProfile.Transcode && ffmpegProfile.NormalizeAudio) { result.AudioCodec = ffmpegProfile.AudioCodec; result.AudioBitrate = ffmpegProfile.AudioBitrate; @@ -152,7 +152,7 @@ namespace ErsatzTV.Core.FFmpeg }; private static bool NeedToScale(FFmpegProfile ffmpegProfile, MediaVersion version) => - ffmpegProfile.NormalizeVideo && + ffmpegProfile.Transcode && ffmpegProfile.NormalizeVideo && IsIncorrectSize(ffmpegProfile.Resolution, version) || IsTooLarge(ffmpegProfile.Resolution, version) || IsOddSize(version); @@ -170,7 +170,7 @@ namespace ErsatzTV.Core.FFmpeg version.Height % 2 == 1 || version.Width % 2 == 1; private static bool NeedToNormalizeVideoCodec(FFmpegProfile ffmpegProfile, MediaStream videoStream) => - ffmpegProfile.NormalizeVideo && ffmpegProfile.VideoCodec != videoStream.Codec; + ffmpegProfile.Transcode && ffmpegProfile.NormalizeVideo && ffmpegProfile.VideoCodec != videoStream.Codec; private static IDisplaySize CalculateScaledSize(FFmpegProfile ffmpegProfile, MediaVersion version) { diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs index a6af725cb..efe371d3b 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs @@ -162,7 +162,8 @@ namespace ErsatzTV.Core.FFmpeg private WatermarkOptions GetWatermarkOptions(Channel channel, Option globalWatermark) { - if (channel.StreamingMode != StreamingMode.HttpLiveStreamingDirect) + if (channel.StreamingMode != StreamingMode.HttpLiveStreamingDirect && channel.FFmpegProfile.Transcode && + channel.FFmpegProfile.NormalizeVideo) { // check for channel watermark if (channel.Watermark != null)