From 9972fc23c6c0dc3a8aab28dc246065ae8d9e330b Mon Sep 17 00:00:00 2001 From: MB-Finski <64466176+MB-Finski@users.noreply.github.com> Date: Fri, 25 Nov 2022 13:59:33 +0200 Subject: [PATCH 1/3] Add support for NVIDIA GPU accelerated transcoding Add a transcoding profile for ffmpeg suitable for using with NVENC. --- stream.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/stream.go b/stream.go index 06b1633e..01492e59 100644 --- a/stream.go +++ b/stream.go @@ -288,12 +288,16 @@ func (s *Stream) transcode(startId int) { // encoder selection CV := "libx264" - // no need to transcode h264 streams for max quality + // Check whether hwaccel should be used if os.Getenv("VAAPI") == "1" { CV = "h264_vaapi" extra := "-hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi" args = append(args, strings.Split(extra, " ")...) - } + } else if os.Getenv("NVENC") == "1" { + CV = "h264_nvenc" + extra := "-hwaccel cuda -hwaccel_output_format cuda" + args = append(args, strings.Split(extra, " ")...) + } // Input specs args = append(args, []string{ @@ -309,7 +313,15 @@ func (s *Stream) transcode(startId int) { // VAAPI format = "format=nv12|vaapi,hwupload" scale = fmt.Sprintf("scale_vaapi=w=%d:h=%d:force_original_aspect_ratio=decrease", s.width, s.height) - } else { + } else if CV == "h264_nvenc" { + // NVENC + format = "format=nv12|cuda,hwupload" + if s.width >= s.height { + scale = fmt.Sprintf("scale_cuda=-2:%d", s.height) + } else { + scale = fmt.Sprintf("scale_cuda=%d:-2", s.width) + } + } else { // x264 format = "format=nv12" if s.width >= s.height { From 0dd14fabe2b19fd093cf08b9c7a4ffd6a73120a8 Mon Sep 17 00:00:00 2001 From: MB-Finski <64466176+MB-Finski@users.noreply.github.com> Date: Tue, 29 Nov 2022 20:33:26 +0200 Subject: [PATCH 2/3] Optimizations for NVENC transcode profile Permormance and quality related optimizations for NVENC. Also contains a bugfix where transcoding with "max"-profile would fail due to a bug in the NVENC itself. --- stream.go | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/stream.go b/stream.go index 01492e59..2c85ee32 100644 --- a/stream.go +++ b/stream.go @@ -315,12 +315,7 @@ func (s *Stream) transcode(startId int) { scale = fmt.Sprintf("scale_vaapi=w=%d:h=%d:force_original_aspect_ratio=decrease", s.width, s.height) } else if CV == "h264_nvenc" { // NVENC - format = "format=nv12|cuda,hwupload" - if s.width >= s.height { - scale = fmt.Sprintf("scale_cuda=-2:%d", s.height) - } else { - scale = fmt.Sprintf("scale_cuda=%d:-2", s.width) - } + scale = fmt.Sprintf("scale_cuda=w=%d:h=%d:force_original_aspect_ratio=decrease:passthrough=0", s.width, s.height) } else { // x264 format = "format=nv12" @@ -333,15 +328,31 @@ func (s *Stream) transcode(startId int) { // do not scale or set bitrate for full quality if s.quality == "max" { - args = append(args, []string{ - "-vf", format, - }...) + if CV == "h264_nvenc" { + // Due to a bug(?) in NVENC, passthrough=0 must be set + args = append(args, []string{ + "-vf", "scale_cuda=passthrough=0", + }...) + } else { + args = append(args, []string{ + "-vf", format, + }...) + } } else { - args = append(args, []string{ - "-vf", fmt.Sprintf("%s,%s", format, scale), - "-maxrate", fmt.Sprintf("%d", s.bitrate), - "-bufsize", fmt.Sprintf("%d", s.bitrate*2), - }...) + if CV == "h264_nvenc" { + args = append(args, []string{ + "-vf", scale, + }...) + } else { + args = append(args, []string{ + "-vf", fmt.Sprintf("%s,%s", format, scale), + }...) + } + // Common arguments + args = append(args, []string{ + "-maxrate", fmt.Sprintf("%d", s.bitrate), + "-bufsize", fmt.Sprintf("%d", s.bitrate*2), + }...) } // Output specs @@ -356,6 +367,15 @@ func (s *Stream) transcode(startId int) { "-low_power", "1", "-global_quality", "25", }...) + } else if CV == "h264_nvenc" { + args = append(args, []string{ + "-preset", "p6", + "-tune", "ll", + "-temporal-aq", "1", + "-rc", "vbr", + "-rc-lookahead","30", + "-cq", "24", + }...) } else if CV == "libx264" { args = append(args, []string{ "-preset", "faster", From a7b7fa5360b9bfe83ea2f7b3dfc91d5422ff35a1 Mon Sep 17 00:00:00 2001 From: MB-Finski <64466176+MB-Finski@users.noreply.github.com> Date: Tue, 29 Nov 2022 23:03:35 +0200 Subject: [PATCH 3/3] Add "format" back into NVENC transcode profile --- stream.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/stream.go b/stream.go index 2c85ee32..ac1b9323 100644 --- a/stream.go +++ b/stream.go @@ -315,6 +315,7 @@ func (s *Stream) transcode(startId int) { scale = fmt.Sprintf("scale_vaapi=w=%d:h=%d:force_original_aspect_ratio=decrease", s.width, s.height) } else if CV == "h264_nvenc" { // NVENC + format = "format=nv12|cuda,hwupload" scale = fmt.Sprintf("scale_cuda=w=%d:h=%d:force_original_aspect_ratio=decrease:passthrough=0", s.width, s.height) } else { // x264 @@ -331,7 +332,7 @@ func (s *Stream) transcode(startId int) { if CV == "h264_nvenc" { // Due to a bug(?) in NVENC, passthrough=0 must be set args = append(args, []string{ - "-vf", "scale_cuda=passthrough=0", + "-vf", fmt.Sprintf("%s,%s", format, "scale_cuda=passthrough=0"), }...) } else { args = append(args, []string{ @@ -339,17 +340,8 @@ func (s *Stream) transcode(startId int) { }...) } } else { - if CV == "h264_nvenc" { - args = append(args, []string{ - "-vf", scale, - }...) - } else { - args = append(args, []string{ - "-vf", fmt.Sprintf("%s,%s", format, scale), - }...) - } - // Common arguments - args = append(args, []string{ + args = append(args, []string{ + "-vf", fmt.Sprintf("%s,%s", format, scale), "-maxrate", fmt.Sprintf("%d", s.bitrate), "-bufsize", fmt.Sprintf("%d", s.bitrate*2), }...)