Browse Source

Enable Rockchip MJPEG encoder for Trickplay (#12610)

Nyanmisaka 9 months ago
parent
commit
36d934f4c0

+ 13 - 9
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -129,7 +129,8 @@ namespace MediaBrowser.Controller.MediaEncoding
         {
             { HardwareAccelerationType.vaapi, _defaultMjpegEncoder + "_vaapi" },
             { HardwareAccelerationType.qsv, _defaultMjpegEncoder + "_qsv" },
-            { HardwareAccelerationType.videotoolbox, _defaultMjpegEncoder + "_videotoolbox" }
+            { HardwareAccelerationType.videotoolbox, _defaultMjpegEncoder + "_videotoolbox" },
+            { HardwareAccelerationType.rkmpp, _defaultMjpegEncoder + "_rkmpp" }
         };
 
         public static readonly string[] LosslessAudioCodecs =
@@ -5435,6 +5436,9 @@ namespace MediaBrowser.Controller.MediaEncoding
             var isSwDecoder = !isRkmppDecoder;
             var isSwEncoder = !isRkmppEncoder;
             var isDrmInDrmOut = isRkmppDecoder && isRkmppEncoder;
+            var isEncoderSupportAfbc = isRkmppEncoder
+                && (vidEncoder.Contains("h264", StringComparison.OrdinalIgnoreCase)
+                    || vidEncoder.Contains("hevc", StringComparison.OrdinalIgnoreCase));
 
             var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
             var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
@@ -5493,7 +5497,7 @@ namespace MediaBrowser.Controller.MediaEncoding
             {
                 // INPUT rkmpp/drm surface(gem/dma-heap)
 
-                var isFullAfbcPipeline = isDrmInDrmOut && !doOclTonemap;
+                var isFullAfbcPipeline = isEncoderSupportAfbc && isDrmInDrmOut && !doOclTonemap;
                 var swapOutputWandH = doRkVppTranspose && swapWAndH;
                 var outFormat = doOclTonemap ? "p010" : "nv12";
                 var hwScalePrefix = doRkVppTranspose ? "vpp" : "scale";
@@ -5531,12 +5535,6 @@ namespace MediaBrowser.Controller.MediaEncoding
             if (doOclTonemap)
             {
                 var tonemapFilter = GetHwTonemapFilter(options, "opencl", "nv12");
-                // enable tradeoffs for performance
-                if (!string.IsNullOrEmpty(tonemapFilter))
-                {
-                    tonemapFilter += ":tradeoff=1";
-                }
-
                 mainFilters.Add(tonemapFilter);
             }
 
@@ -5607,7 +5605,13 @@ namespace MediaBrowser.Controller.MediaEncoding
                     subFilters.Add("hwupload=derive_device=rkmpp");
 
                     // try enabling AFBC to save DDR bandwidth
-                    overlayFilters.Add("overlay_rkrga=eof_action=pass:repeatlast=0:format=nv12:afbc=1");
+                    var hwOverlayFilter = "overlay_rkrga=eof_action=pass:repeatlast=0:format=nv12";
+                    if (isEncoderSupportAfbc)
+                    {
+                        hwOverlayFilter += ":afbc=1";
+                    }
+
+                    overlayFilters.Add(hwOverlayFilter);
                 }
             }
             else if (memoryOutput)

+ 2 - 1
MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs

@@ -93,7 +93,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
             "hevc_videotoolbox",
             "mjpeg_videotoolbox",
             "h264_rkmpp",
-            "hevc_rkmpp"
+            "hevc_rkmpp",
+            "mjpeg_rkmpp"
         };
 
         private static readonly string[] _requiredFilters = new[]

+ 19 - 10
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -896,21 +896,30 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 throw new InvalidOperationException("Empty or invalid input argument.");
             }
 
-            float? encoderQuality = qualityScale;
-            if (vidEncoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase))
+            // ffmpeg qscale is a value from 1-31, with 1 being best quality and 31 being worst
+            // jpeg quality is a value from 0-100, with 0 being worst quality and 100 being best
+            var encoderQuality = Math.Clamp(qualityScale ?? 4, 1, 31);
+            var encoderQualityOption = "-qscale:v ";
+
+            if (vidEncoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase)
+                || vidEncoder.Contains("qsv", StringComparison.OrdinalIgnoreCase))
             {
-                // vaapi's mjpeg encoder uses jpeg quality divided by QP2LAMBDA (118) as input, instead of ffmpeg defined qscale
-                // ffmpeg qscale is a value from 1-31, with 1 being best quality and 31 being worst
-                // jpeg quality is a value from 0-100, with 0 being worst quality and 100 being best
-                encoderQuality = (100 - ((qualityScale - 1) * (100 / 30))) / 118;
+                // vaapi and qsv's mjpeg encoder use jpeg quality as input, instead of ffmpeg defined qscale
+                encoderQuality = 100 - ((encoderQuality - 1) * (100 / 30));
+                encoderQualityOption = "-global_quality:v ";
             }
 
             if (vidEncoder.Contains("videotoolbox", StringComparison.OrdinalIgnoreCase))
             {
                 // videotoolbox's mjpeg encoder uses jpeg quality scaled to QP2LAMBDA (118) instead of ffmpeg defined qscale
-                // ffmpeg qscale is a value from 1-31, with 1 being best quality and 31 being worst
-                // jpeg quality is a value from 0-100, with 0 being worst quality and 100 being best
-                encoderQuality = 118 - ((qualityScale - 1) * (118 / 30));
+                encoderQuality = 118 - ((encoderQuality - 1) * (118 / 30));
+            }
+
+            if (vidEncoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase))
+            {
+                // rkmpp's mjpeg encoder uses jpeg quality as input (max is 99, not 100), instead of ffmpeg defined qscale
+                encoderQuality = 99 - ((encoderQuality - 1) * (99 / 30));
+                encoderQualityOption = "-qp_init:v ";
             }
 
             // Output arguments
@@ -926,7 +935,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 filterParam,
                 outputThreads.GetValueOrDefault(_threads),
                 vidEncoder,
-                qualityScale.HasValue ? "-qscale:v " + encoderQuality.Value.ToString(CultureInfo.InvariantCulture) + " " : string.Empty,
+                encoderQualityOption + encoderQuality + " ",
                 vidEncoder.Contains("videotoolbox", StringComparison.InvariantCultureIgnoreCase) ? "-allow_sw 1 " : string.Empty, // allow_sw fallback for some intel macs
                 "image2",
                 outputPath);