aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api/Playback/BaseStreamingService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api/Playback/BaseStreamingService.cs')
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs129
1 files changed, 91 insertions, 38 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index bff6ec2ff..4c8b918c6 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -314,6 +314,10 @@ namespace MediaBrowser.Api.Playback
{
return GetAvailableEncoder("h264_omx", defaultEncoder);
}
+ if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetAvailableEncoder("h264_vaapi", defaultEncoder);
+ }
}
return defaultEncoder;
@@ -427,7 +431,8 @@ namespace MediaBrowser.Api.Playback
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
{
- if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
+ if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
+ !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
// not supported by h264_omx
param += " -profile:v " + state.VideoRequest.Profile;
@@ -482,7 +487,8 @@ namespace MediaBrowser.Api.Playback
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_nvenc", StringComparison.OrdinalIgnoreCase) &&
+ !string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
param = "-pix_fmt yuv420p " + param;
}
@@ -548,59 +554,97 @@ namespace MediaBrowser.Api.Playback
var filters = new List<string>();
- if (state.DeInterlace)
+ if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+ {
+ filters.Add("format=nv12|vaapi");
+ filters.Add("hwupload");
+ }
+ else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
filters.Add("yadif=0:-1:0");
}
- // If fixed dimensions were supplied
- if (request.Width.HasValue && request.Height.HasValue)
+ if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
- var widthParam = request.Width.Value.ToString(UsCulture);
- var heightParam = request.Height.Value.ToString(UsCulture);
+ // Work around vaapi's reduced scaling features
+ var scaler = "scale_vaapi";
- filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam));
- }
+ // Given the input dimensions (inputWidth, inputHeight), determine the output dimensions
+ // (outputWidth, outputHeight). The user may request precise output dimensions or maximum
+ // output dimensions. Output dimensions are guaranteed to be even.
+ decimal inputWidth = Convert.ToDecimal(state.VideoStream.Width);
+ decimal inputHeight = Convert.ToDecimal(state.VideoStream.Height);
+ decimal outputWidth = request.Width.HasValue ? Convert.ToDecimal(request.Width.Value) : inputWidth;
+ decimal outputHeight = request.Height.HasValue ? Convert.ToDecimal(request.Height.Value) : inputHeight;
+ decimal maximumWidth = request.MaxWidth.HasValue ? Convert.ToDecimal(request.MaxWidth.Value) : outputWidth;
+ decimal maximumHeight = request.MaxHeight.HasValue ? Convert.ToDecimal(request.MaxHeight.Value) : outputHeight;
- // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
- else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
- {
- var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
- var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
+ if (outputWidth > maximumWidth || outputHeight > maximumHeight)
+ {
+ var scale = Math.Min(maximumWidth / outputWidth, maximumHeight / outputHeight);
+ outputWidth = Math.Min(maximumWidth, Math.Truncate(outputWidth * scale));
+ outputHeight = Math.Min(maximumHeight, Math.Truncate(outputHeight * scale));
+ }
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
- }
+ outputWidth = 2 * Math.Truncate(outputWidth / 2);
+ outputHeight = 2 * Math.Truncate(outputHeight / 2);
- // If a fixed width was requested
- else if (request.Width.HasValue)
+ if (outputWidth != inputWidth || outputHeight != inputHeight)
+ {
+ filters.Add(string.Format("{0}=w={1}:h={2}", scaler, outputWidth.ToString(UsCulture), outputHeight.ToString(UsCulture)));
+ }
+ }
+ else
{
- var widthParam = request.Width.Value.ToString(UsCulture);
+ // If fixed dimensions were supplied
+ if (request.Width.HasValue && request.Height.HasValue)
+ {
+ var widthParam = request.Width.Value.ToString(UsCulture);
+ var heightParam = request.Height.Value.ToString(UsCulture);
- filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam));
- }
+ filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam));
+ }
- // If a fixed height was requested
- else if (request.Height.HasValue)
- {
- var heightParam = request.Height.Value.ToString(UsCulture);
+ // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
+ else if (request.MaxWidth.HasValue && request.MaxHeight.HasValue)
+ {
+ var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
+ var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
- filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam));
- }
+ filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+ }
- // If a max width was requested
- else if (request.MaxWidth.HasValue)
- {
- var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
+ // If a fixed width was requested
+ else if (request.Width.HasValue)
+ {
+ var widthParam = request.Width.Value.ToString(UsCulture);
- filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam));
- }
+ filters.Add(string.Format("scale={0}:trunc(ow/a/2)*2", widthParam));
+ }
- // If a max height was requested
- else if (request.MaxHeight.HasValue)
- {
- var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
+ // If a fixed height was requested
+ else if (request.Height.HasValue)
+ {
+ var heightParam = request.Height.Value.ToString(UsCulture);
+
+ filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam));
+ }
+
+ // If a max width was requested
+ else if (request.MaxWidth.HasValue)
+ {
+ var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
+
+ filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam));
+ }
+
+ // If a max height was requested
+ else if (request.MaxHeight.HasValue)
+ {
+ var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture);
- filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam));
+ filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(ih\\,{0})", maxHeightParam));
+ }
}
var output = string.Empty;
@@ -935,6 +979,15 @@ namespace MediaBrowser.Api.Playback
}
}
+ if (state.VideoRequest != null)
+ {
+ 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;
+ }
+ }
+
return arg.Trim();
}