|  | @@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |          private const string VaapiAlias = "va";
 | 
	
		
			
				|  |  |          private const string D3d11vaAlias = "dx11";
 | 
	
		
			
				|  |  |          private const string VideotoolboxAlias = "vt";
 | 
	
		
			
				|  |  | +        private const string RkmppAlias = "rk";
 | 
	
		
			
				|  |  |          private const string OpenclAlias = "ocl";
 | 
	
		
			
				|  |  |          private const string CudaAlias = "cu";
 | 
	
		
			
				|  |  |          private const string DrmAlias = "dr";
 | 
	
	
		
			
				|  | @@ -161,6 +162,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                      { "vaapi",                hwEncoder + "_vaapi" },
 | 
	
		
			
				|  |  |                      { "videotoolbox",         hwEncoder + "_videotoolbox" },
 | 
	
		
			
				|  |  |                      { "v4l2m2m",              hwEncoder + "_v4l2m2m" },
 | 
	
		
			
				|  |  | +                    { "rkmpp",                hwEncoder + "_rkmpp" },
 | 
	
		
			
				|  |  |                  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (!string.IsNullOrEmpty(hwType)
 | 
	
	
		
			
				|  | @@ -217,6 +219,14 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                     && _mediaEncoder.SupportsFilter("hwupload_vaapi");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        private bool IsRkmppFullSupported()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            return _mediaEncoder.SupportsHwaccel("rkmpp")
 | 
	
		
			
				|  |  | +                   && _mediaEncoder.SupportsFilter("scale_rkrga")
 | 
	
		
			
				|  |  | +                   && _mediaEncoder.SupportsFilter("vpp_rkrga")
 | 
	
		
			
				|  |  | +                   && _mediaEncoder.SupportsFilter("overlay_rkrga");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          private bool IsOpenclFullSupported()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              return _mediaEncoder.SupportsHwaccel("opencl")
 | 
	
	
		
			
				|  | @@ -696,6 +706,14 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              return codec.ToLowerInvariant();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        private string GetRkmppDeviceArgs(string alias)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            alias ??= RkmppAlias;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // device selection in rk is not supported.
 | 
	
		
			
				|  |  | +            return " -init_hw_device rkmpp=" + alias;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          private string GetVideoToolboxDeviceArgs(string alias)
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              alias ??= VideotoolboxAlias;
 | 
	
	
		
			
				|  | @@ -1056,6 +1074,33 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                  // no videotoolbox hw filter.
 | 
	
		
			
				|  |  |                  args.Append(GetVideoToolboxDeviceArgs(VideotoolboxAlias));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            else if (string.Equals(optHwaccelType, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (!isLinux || !_mediaEncoder.SupportsHwaccel("rkmpp"))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return string.Empty;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var isRkmppDecoder = vidDecoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +                var isRkmppEncoder = vidEncoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +                if (!isRkmppDecoder && !isRkmppEncoder)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return string.Empty;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                args.Append(GetRkmppDeviceArgs(RkmppAlias));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var filterDevArgs = string.Empty;
 | 
	
		
			
				|  |  | +                var doOclTonemap = isHwTonemapAvailable && IsOpenclFullSupported();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (doOclTonemap && !isRkmppDecoder)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    args.Append(GetOpenclDeviceArgs(0, null, RkmppAlias, OpenclAlias));
 | 
	
		
			
				|  |  | +                    filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                args.Append(filterDevArgs);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              if (!string.IsNullOrEmpty(vidDecoder))
 | 
	
		
			
				|  |  |              {
 | 
	
	
		
			
				|  | @@ -1472,8 +1517,10 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "h264_amf", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                || string.Equals(codec, "h264_rkmpp", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "hevc_qsv", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                || string.Equals(codec, "hevc_rkmpp", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "av1_qsv", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "av1_nvenc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                  || string.Equals(codec, "av1_amf", StringComparison.OrdinalIgnoreCase)
 | 
	
	
		
			
				|  | @@ -1913,20 +1960,22 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                  profile = "constrained_baseline";
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // libx264, h264_qsv and h264_nvenc does not support Constrained Baseline profile, force Baseline in this case.
 | 
	
		
			
				|  |  | +            // libx264, h264_{qsv,nvenc,rkmpp} does not support Constrained Baseline profile, force Baseline in this case.
 | 
	
		
			
				|  |  |              if ((string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                   || string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | -                 || string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                 || string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                 || string.Equals(videoEncoder, "h264_rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  && profile.Contains("baseline", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  profile = "baseline";
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // libx264, h264_qsv, h264_nvenc and h264_vaapi does not support Constrained High profile, force High in this case.
 | 
	
		
			
				|  |  | +            // libx264, h264_{qsv,nvenc,vaapi,rkmpp} does not support Constrained High profile, force High in this case.
 | 
	
		
			
				|  |  |              if ((string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                   || string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                   || string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | -                 || string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                 || string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                 || string.Equals(videoEncoder, "h264_rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  && profile.Contains("high", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  profile = "high";
 | 
	
	
		
			
				|  | @@ -2010,6 +2059,11 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                          param += " -level " + level;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +                else if (string.Equals(videoEncoder, "h264_rkmpp", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                         || string.Equals(videoEncoder, "hevc_rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    param += " -level " + level;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |                  else if (!string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      param += " -level " + level;
 | 
	
	
		
			
				|  | @@ -2828,6 +2882,48 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              return (outputWidth, outputHeight);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        public static bool IsScaleRatioSupported(
 | 
	
		
			
				|  |  | +            int? videoWidth,
 | 
	
		
			
				|  |  | +            int? videoHeight,
 | 
	
		
			
				|  |  | +            int? requestedWidth,
 | 
	
		
			
				|  |  | +            int? requestedHeight,
 | 
	
		
			
				|  |  | +            int? requestedMaxWidth,
 | 
	
		
			
				|  |  | +            int? requestedMaxHeight,
 | 
	
		
			
				|  |  | +            double? maxScaleRatio)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var (outWidth, outHeight) = GetFixedOutputSize(
 | 
	
		
			
				|  |  | +                videoWidth,
 | 
	
		
			
				|  |  | +                videoHeight,
 | 
	
		
			
				|  |  | +                requestedWidth,
 | 
	
		
			
				|  |  | +                requestedHeight,
 | 
	
		
			
				|  |  | +                requestedMaxWidth,
 | 
	
		
			
				|  |  | +                requestedMaxHeight);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (!videoWidth.HasValue
 | 
	
		
			
				|  |  | +                 || !videoHeight.HasValue
 | 
	
		
			
				|  |  | +                 || !outWidth.HasValue
 | 
	
		
			
				|  |  | +                 || !outHeight.HasValue
 | 
	
		
			
				|  |  | +                 || !maxScaleRatio.HasValue
 | 
	
		
			
				|  |  | +                 || (maxScaleRatio.Value < 1.0f))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var minScaleRatio = 1.0f / maxScaleRatio;
 | 
	
		
			
				|  |  | +            var scaleRatioW = (double)outWidth / (double)videoWidth;
 | 
	
		
			
				|  |  | +            var scaleRatioH = (double)outHeight / (double)videoHeight;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (scaleRatioW < minScaleRatio
 | 
	
		
			
				|  |  | +                || scaleRatioW > maxScaleRatio
 | 
	
		
			
				|  |  | +                || scaleRatioH < minScaleRatio
 | 
	
		
			
				|  |  | +                || scaleRatioH > maxScaleRatio)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return true;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          public static string GetHwScaleFilter(
 | 
	
		
			
				|  |  |              string hwScaleSuffix,
 | 
	
		
			
				|  |  |              string videoFormat,
 | 
	
	
		
			
				|  | @@ -4910,6 +5006,237 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              return (newfilters, swFilterChain.SubFilters, swFilterChain.OverlayFilters);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets the parameter of Rockchip RKMPP/RKRGA filter chain.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="state">Encoding state.</param>
 | 
	
		
			
				|  |  | +        /// <param name="options">Encoding options.</param>
 | 
	
		
			
				|  |  | +        /// <param name="vidEncoder">Video encoder to use.</param>
 | 
	
		
			
				|  |  | +        /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns>
 | 
	
		
			
				|  |  | +        public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetRkmppVidFilterChain(
 | 
	
		
			
				|  |  | +            EncodingJobInfo state,
 | 
	
		
			
				|  |  | +            EncodingOptions options,
 | 
	
		
			
				|  |  | +            string vidEncoder)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (!string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return (null, null, null);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var isLinux = OperatingSystem.IsLinux();
 | 
	
		
			
				|  |  | +            var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty;
 | 
	
		
			
				|  |  | +            var isSwDecoder = string.IsNullOrEmpty(vidDecoder);
 | 
	
		
			
				|  |  | +            var isSwEncoder = !vidEncoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +            var isRkmppOclSupported = isLinux && IsRkmppFullSupported() && IsOpenclFullSupported();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if ((isSwDecoder && isSwEncoder)
 | 
	
		
			
				|  |  | +                || !isRkmppOclSupported
 | 
	
		
			
				|  |  | +                || !_mediaEncoder.SupportsFilter("alphasrc"))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return GetSwVidFilterChain(state, options, vidEncoder);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // prefered rkmpp + rkrga + opencl filters pipeline
 | 
	
		
			
				|  |  | +            if (isRkmppOclSupported)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return GetRkmppVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return (null, null, null);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetRkmppVidFiltersPrefered(
 | 
	
		
			
				|  |  | +            EncodingJobInfo state,
 | 
	
		
			
				|  |  | +            EncodingOptions options,
 | 
	
		
			
				|  |  | +            string vidDecoder,
 | 
	
		
			
				|  |  | +            string vidEncoder)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var inW = state.VideoStream?.Width;
 | 
	
		
			
				|  |  | +            var inH = state.VideoStream?.Height;
 | 
	
		
			
				|  |  | +            var reqW = state.BaseRequest.Width;
 | 
	
		
			
				|  |  | +            var reqH = state.BaseRequest.Height;
 | 
	
		
			
				|  |  | +            var reqMaxW = state.BaseRequest.MaxWidth;
 | 
	
		
			
				|  |  | +            var reqMaxH = state.BaseRequest.MaxHeight;
 | 
	
		
			
				|  |  | +            var threeDFormat = state.MediaSource.Video3DFormat;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var isRkmppDecoder = vidDecoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +            var isRkmppEncoder = vidEncoder.Contains("rkmpp", StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +            var isSwDecoder = !isRkmppDecoder;
 | 
	
		
			
				|  |  | +            var isSwEncoder = !isRkmppEncoder;
 | 
	
		
			
				|  |  | +            var isDrmInDrmOut = isRkmppDecoder && isRkmppEncoder;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
 | 
	
		
			
				|  |  | +            var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
 | 
	
		
			
				|  |  | +            var doDeintH2645 = doDeintH264 || doDeintHevc;
 | 
	
		
			
				|  |  | +            var doOclTonemap = IsHwTonemapAvailable(state, options);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var hasSubs = state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
 | 
	
		
			
				|  |  | +            var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream;
 | 
	
		
			
				|  |  | +            var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream;
 | 
	
		
			
				|  |  | +            var hasAssSubs = hasSubs
 | 
	
		
			
				|  |  | +                && (string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            /* Make main filters for video stream */
 | 
	
		
			
				|  |  | +            var mainFilters = new List<string>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            mainFilters.Add(GetOverwriteColorPropertiesParam(state, doOclTonemap));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (isSwDecoder)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // INPUT sw surface(memory)
 | 
	
		
			
				|  |  | +                // sw deint
 | 
	
		
			
				|  |  | +                if (doDeintH2645)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var swDeintFilter = GetSwDeinterlaceFilter(state, options);
 | 
	
		
			
				|  |  | +                    mainFilters.Add(swDeintFilter);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var outFormat = doOclTonemap ? "yuv420p10le" : (hasGraphicalSubs ? "yuv420p" : "nv12");
 | 
	
		
			
				|  |  | +                var swScaleFilter = GetSwScaleFilter(state, options, vidEncoder, inW, inH, threeDFormat, reqW, reqH, reqMaxW, reqMaxH);
 | 
	
		
			
				|  |  | +                if (!string.IsNullOrEmpty(swScaleFilter))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    swScaleFilter += ":flags=fast_bilinear";
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // sw scale
 | 
	
		
			
				|  |  | +                mainFilters.Add(swScaleFilter);
 | 
	
		
			
				|  |  | +                mainFilters.Add("format=" + outFormat);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // keep video at memory except ocl tonemap,
 | 
	
		
			
				|  |  | +                // since the overhead caused by hwupload >>> using sw filter.
 | 
	
		
			
				|  |  | +                // sw => hw
 | 
	
		
			
				|  |  | +                if (doOclTonemap)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    mainFilters.Add("hwupload=derive_device=opencl");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else if (isRkmppDecoder)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // INPUT rkmpp/drm surface(gem/dma-heap)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                var isFullAfbcPipeline = isDrmInDrmOut && !doOclTonemap;
 | 
	
		
			
				|  |  | +                var outFormat = doOclTonemap ? "p010" : "nv12";
 | 
	
		
			
				|  |  | +                var hwScaleFilter = GetHwScaleFilter("rkrga", outFormat, inW, inH, reqW, reqH, reqMaxW, reqMaxH);
 | 
	
		
			
				|  |  | +                var hwScaleFilter2 = GetHwScaleFilter("rkrga", string.Empty, inW, inH, reqW, reqH, reqMaxW, reqMaxH);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (!hasSubs
 | 
	
		
			
				|  |  | +                     || !isFullAfbcPipeline
 | 
	
		
			
				|  |  | +                     || !string.IsNullOrEmpty(hwScaleFilter2))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // try enabling AFBC to save DDR bandwidth
 | 
	
		
			
				|  |  | +                    if (!string.IsNullOrEmpty(hwScaleFilter) && isFullAfbcPipeline)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        hwScaleFilter += ":afbc=1";
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    // hw scale
 | 
	
		
			
				|  |  | +                    mainFilters.Add(hwScaleFilter);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (doOclTonemap && isRkmppDecoder)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // map from rkmpp/drm to opencl via drm-opencl interop.
 | 
	
		
			
				|  |  | +                mainFilters.Add("hwmap=derive_device=opencl:mode=read");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // ocl tonemap
 | 
	
		
			
				|  |  | +            if (doOclTonemap)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                var tonemapFilter = GetHwTonemapFilter(options, "opencl", "nv12");
 | 
	
		
			
				|  |  | +                // enable tradeoffs for performance
 | 
	
		
			
				|  |  | +                if (!string.IsNullOrEmpty(tonemapFilter))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    tonemapFilter += ":tradeoff=1";
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                mainFilters.Add(tonemapFilter);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var memoryOutput = false;
 | 
	
		
			
				|  |  | +            var isUploadForOclTonemap = isSwDecoder && doOclTonemap;
 | 
	
		
			
				|  |  | +            if ((isRkmppDecoder && isSwEncoder) || isUploadForOclTonemap)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                memoryOutput = true;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // OUTPUT nv12 surface(memory)
 | 
	
		
			
				|  |  | +                mainFilters.Add("hwdownload");
 | 
	
		
			
				|  |  | +                mainFilters.Add("format=nv12");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // OUTPUT nv12 surface(memory)
 | 
	
		
			
				|  |  | +            if (isSwDecoder && isRkmppEncoder)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                memoryOutput = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (memoryOutput)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // text subtitles
 | 
	
		
			
				|  |  | +                if (hasTextSubs)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var textSubtitlesFilter = GetTextSubtitlesFilter(state, false, false);
 | 
	
		
			
				|  |  | +                    mainFilters.Add(textSubtitlesFilter);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (isDrmInDrmOut)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (doOclTonemap)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // OUTPUT drm(nv12) surface(gem/dma-heap)
 | 
	
		
			
				|  |  | +                    // reverse-mapping via drm-opencl interop.
 | 
	
		
			
				|  |  | +                    mainFilters.Add("hwmap=derive_device=rkmpp:mode=write:reverse=1");
 | 
	
		
			
				|  |  | +                    mainFilters.Add("format=drm_prime");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            /* Make sub and overlay filters for subtitle stream */
 | 
	
		
			
				|  |  | +            var subFilters = new List<string>();
 | 
	
		
			
				|  |  | +            var overlayFilters = new List<string>();
 | 
	
		
			
				|  |  | +            if (isDrmInDrmOut)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (hasSubs)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    if (hasGraphicalSubs)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        var subPreProcFilters = GetGraphicalSubPreProcessFilters(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
 | 
	
		
			
				|  |  | +                        subFilters.Add(subPreProcFilters);
 | 
	
		
			
				|  |  | +                        subFilters.Add("format=bgra");
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    else if (hasTextSubs)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        var framerate = state.VideoStream?.RealFrameRate;
 | 
	
		
			
				|  |  | +                        var subFramerate = hasAssSubs ? Math.Min(framerate ?? 25, 60) : 10;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        // alphasrc=s=1280x720:r=10:start=0,format=bgra,subtitles,hwupload
 | 
	
		
			
				|  |  | +                        var alphaSrcFilter = GetAlphaSrcFilter(state, inW, inH, reqW, reqH, reqMaxW, reqMaxH, subFramerate);
 | 
	
		
			
				|  |  | +                        var subTextSubtitlesFilter = GetTextSubtitlesFilter(state, true, true);
 | 
	
		
			
				|  |  | +                        subFilters.Add(alphaSrcFilter);
 | 
	
		
			
				|  |  | +                        subFilters.Add("format=bgra");
 | 
	
		
			
				|  |  | +                        subFilters.Add(subTextSubtitlesFilter);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    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");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else if (memoryOutput)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (hasGraphicalSubs)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var subPreProcFilters = GetGraphicalSubPreProcessFilters(inW, inH, reqW, reqH, reqMaxW, reqMaxH);
 | 
	
		
			
				|  |  | +                    subFilters.Add(subPreProcFilters);
 | 
	
		
			
				|  |  | +                    overlayFilters.Add("overlay=eof_action=pass:repeatlast=0");
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return (mainFilters, subFilters, overlayFilters);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets the parameter of video processing filters.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -4956,6 +5283,10 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  (mainFilters, subFilters, overlayFilters) = GetAppleVidFilterChain(state, options, outputVideoCodec);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            else if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                (mainFilters, subFilters, overlayFilters) = GetRkmppVidFilterChain(state, options, outputVideoCodec);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              else
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  (mainFilters, subFilters, overlayFilters) = GetSwVidFilterChain(state, options, outputVideoCodec);
 | 
	
	
		
			
				|  | @@ -5087,18 +5418,21 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (string.Equals(videoStream.PixelFormat, "yuv420p", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                      || string.Equals(videoStream.PixelFormat, "yuvj420p", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(videoStream.PixelFormat, "yuv422p", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                      || string.Equals(videoStream.PixelFormat, "yuv444p", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      return 8;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (string.Equals(videoStream.PixelFormat, "yuv420p10le", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(videoStream.PixelFormat, "yuv422p10le", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                      || string.Equals(videoStream.PixelFormat, "yuv444p10le", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      return 10;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (string.Equals(videoStream.PixelFormat, "yuv420p12le", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(videoStream.PixelFormat, "yuv422p12le", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                      || string.Equals(videoStream.PixelFormat, "yuv444p12le", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      return 12;
 | 
	
	
		
			
				|  | @@ -5151,7 +5485,12 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                           || string.Equals(videoStream.Codec, "vp9", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  |                           || string.Equals(videoStream.Codec, "av1", StringComparison.OrdinalIgnoreCase)))
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  | -                    return null;
 | 
	
		
			
				|  |  | +                    // One exception is that RKMPP decoder can handle H.264 High 10.
 | 
	
		
			
				|  |  | +                    if (!(string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                          && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase)))
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        return null;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  if (string.Equals(options.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
 | 
	
	
		
			
				|  | @@ -5178,6 +5517,11 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                  {
 | 
	
		
			
				|  |  |                      return GetVideotoolboxVidDecoder(state, options, videoStream, bitDepth);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetRkmppVidDecoder(state, options, videoStream, bitDepth);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var whichCodec = videoStream.Codec;
 | 
	
	
		
			
				|  | @@ -5243,6 +5587,11 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                  return null;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            if (string.Equals(decoderSuffix, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              return isCodecAvailable ? (" -c:v " + decoderName) : null;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -5265,6 +5614,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              var isCudaSupported = (isLinux || isWindows) && IsCudaFullSupported();
 | 
	
		
			
				|  |  |              var isQsvSupported = (isLinux || isWindows) && _mediaEncoder.SupportsHwaccel("qsv");
 | 
	
		
			
				|  |  |              var isVideotoolboxSupported = isMacOS && _mediaEncoder.SupportsHwaccel("videotoolbox");
 | 
	
		
			
				|  |  | +            var isRkmppSupported = isLinux && IsRkmppFullSupported();
 | 
	
		
			
				|  |  |              var isCodecAvailable = options.HardwareDecodingCodecs.Contains(videoCodec, StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var ffmpegVersion = _mediaEncoder.EncoderVersion;
 | 
	
	
		
			
				|  | @@ -5367,6 +5717,14 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |                  return " -hwaccel videotoolbox" + (outputHwSurface ? " -hwaccel_output_format videotoolbox_vld" : string.Empty);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            // Rockchip rkmpp
 | 
	
		
			
				|  |  | +            if (string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                && isRkmppSupported
 | 
	
		
			
				|  |  | +                && isCodecAvailable)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return " -hwaccel rkmpp" + (outputHwSurface ? " -hwaccel_output_format drm_prime" : string.Empty);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              return null;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -5673,6 +6031,102 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
	
		
			
				|  |  |              return null;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        public string GetRkmppVidDecoder(EncodingJobInfo state, EncodingOptions options, MediaStream videoStream, int bitDepth)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var isLinux = OperatingSystem.IsLinux();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (!isLinux
 | 
	
		
			
				|  |  | +                || !string.Equals(options.HardwareAccelerationType, "rkmpp", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var inW = state.VideoStream?.Width;
 | 
	
		
			
				|  |  | +            var inH = state.VideoStream?.Height;
 | 
	
		
			
				|  |  | +            var reqW = state.BaseRequest.Width;
 | 
	
		
			
				|  |  | +            var reqH = state.BaseRequest.Height;
 | 
	
		
			
				|  |  | +            var reqMaxW = state.BaseRequest.MaxWidth;
 | 
	
		
			
				|  |  | +            var reqMaxH = state.BaseRequest.MaxHeight;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // rkrga RGA2e supports range from 1/16 to 16
 | 
	
		
			
				|  |  | +            if (!IsScaleRatioSupported(inW, inH, reqW, reqH, reqMaxW, reqMaxH, 16.0f))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var isRkmppOclSupported = IsRkmppFullSupported() && IsOpenclFullSupported();
 | 
	
		
			
				|  |  | +            var hwSurface = isRkmppOclSupported
 | 
	
		
			
				|  |  | +                && _mediaEncoder.SupportsFilter("alphasrc");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // rkrga RGA3 supports range from 1/8 to 8
 | 
	
		
			
				|  |  | +            var isAfbcSupported = hwSurface && IsScaleRatioSupported(inW, inH, reqW, reqH, reqMaxW, reqMaxH, 8.0f);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // TODO: add more 8/10bit and 4:2:2 formats for Rkmpp after finishing the ffcheck tool
 | 
	
		
			
				|  |  | +            var is8bitSwFormatsRkmpp = string.Equals("yuv420p", videoStream.PixelFormat, StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                                       || string.Equals("yuvj420p", videoStream.PixelFormat, StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +            var is10bitSwFormatsRkmpp = string.Equals("yuv420p10le", videoStream.PixelFormat, StringComparison.OrdinalIgnoreCase);
 | 
	
		
			
				|  |  | +            var is8_10bitSwFormatsRkmpp = is8bitSwFormatsRkmpp || is10bitSwFormatsRkmpp;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // nv15 and nv20 are bit-stream only formats
 | 
	
		
			
				|  |  | +            if (is10bitSwFormatsRkmpp && !hwSurface)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (is8bitSwFormatsRkmpp)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "mpeg1video", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetHwaccelType(state, options, "mpeg1video", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "mpeg2video", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetHwaccelType(state, options, "mpeg2video", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetHwaccelType(state, options, "mpeg4", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "vp8", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetHwaccelType(state, options, "vp8", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (is8_10bitSwFormatsRkmpp)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "avc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var accelType = GetHwaccelType(state, options, "h264", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                    return accelType + ((!string.IsNullOrEmpty(accelType) && isAfbcSupported) ? " -afbc rga" : string.Empty);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
 | 
	
		
			
				|  |  | +                    || string.Equals(videoStream.Codec, "h265", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var accelType = GetHwaccelType(state, options, "hevc", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                    return accelType + ((!string.IsNullOrEmpty(accelType) && isAfbcSupported) ? " -afbc rga" : string.Empty);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "vp9", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var accelType = GetHwaccelType(state, options, "vp9", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                    return accelType + ((!string.IsNullOrEmpty(accelType) && isAfbcSupported) ? " -afbc rga" : string.Empty);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (string.Equals(videoStream.Codec, "av1", StringComparison.OrdinalIgnoreCase))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return GetHwaccelType(state, options, "av1", bitDepth, hwSurface);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets the number of threads.
 | 
	
		
			
				|  |  |          /// </summary>
 |