added setting for intel qsv hardware decoding

This commit is contained in:
Luke Pulverenti 2015-09-17 23:08:45 -04:00
parent 2acd1665c9
commit 5340bfe8da
7 changed files with 132 additions and 69 deletions

View File

@ -290,13 +290,6 @@ namespace MediaBrowser.Api.Playback
{
get
{
var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder;
if (!string.IsNullOrWhiteSpace(lib))
{
return lib;
}
return "libx264";
}
}
@ -809,6 +802,46 @@ namespace MediaBrowser.Api.Playback
return "copy";
}
/// <summary>
/// Gets the name of the output video codec
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.String.</returns>
protected string GetVideoDecoder(StreamState state)
{
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase))
{
if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
{
switch (state.MediaSource.VideoStream.Codec.ToLower())
{
case "avc":
case "h264":
if (MediaEncoder.SupportsDecoder("h264_qsv"))
{
return "-c:v h264_qsv ";
}
break;
case "mpeg2video":
if (MediaEncoder.SupportsDecoder("mpeg2_qsv"))
{
return "-c:v mpeg2_qsv ";
}
break;
case "vc1":
if (MediaEncoder.SupportsDecoder("vc1_qsv"))
{
return "-c:v vc1_qsv ";
}
break;
}
}
}
// leave blank so ffmpeg will decide
return string.Empty;
}
/// <summary>
/// Gets the input argument.
/// </summary>
@ -816,7 +849,7 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
var arg = "-i " + GetInputPathArgument(state);
var arg = string.Format("{1}-i {0}", GetInputPathArgument(state), GetVideoDecoder(state));
if (state.SubtitleStream != null)
{
@ -826,7 +859,7 @@ namespace MediaBrowser.Api.Playback
}
}
return arg;
return arg.Trim();
}
private string GetInputPathArgument(StreamState state)

View File

@ -24,6 +24,13 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <value>The version.</value>
string Version { get; }
/// <summary>
/// Supportses the decoder.
/// </summary>
/// <param name="decoder">The decoder.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool SupportsDecoder(string decoder);
/// <summary>
/// Extracts the audio image.
/// </summary>

View File

@ -97,6 +97,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
FFMpegPath = ffMpegPath;
}
public void SetAvailableEncoders(List<string> list)
{
}
private List<string> _decoders = new List<string>();
public void SetAvailableDecoders(List<string> list)
{
_decoders = list.ToList();
}
public bool SupportsDecoder(string decoder)
{
return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Gets the encoder path.
/// </summary>

View File

@ -6,14 +6,13 @@ namespace MediaBrowser.Model.Configuration
public int EncodingThreadCount { get; set; }
public string TranscodingTempPath { get; set; }
public double DownMixAudioBoost { get; set; }
public string H264Encoder { get; set; }
public bool EnableDebugLogging { get; set; }
public bool EnableThrottling { get; set; }
public int ThrottleThresholdInSeconds { get; set; }
public string HardwareVideoDecoder { get; set; }
public EncodingOptions()
{
H264Encoder = "libx264";
DownMixAudioBoost = 2;
EnableThrottling = true;
ThrottleThresholdInSeconds = 120;

View File

@ -595,9 +595,7 @@ namespace MediaBrowser.Server.Startup.Common
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment)
.GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false);
new FFmpegValidator(Logger, ApplicationPaths, FileSystemManager).Validate(info);
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"),
var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"),
JsonSerializer,
info.EncoderPath,
info.ProbePath,
@ -611,7 +609,17 @@ namespace MediaBrowser.Server.Startup.Common
SessionManager,
() => SubtitleEncoder,
() => MediaSourceManager);
MediaEncoder = mediaEncoder;
RegisterSingleInstance(MediaEncoder);
Task.Run(() =>
{
var result = new FFmpegValidator(Logger, ApplicationPaths, FileSystemManager).Validate(info);
mediaEncoder.SetAvailableDecoders(result.Item1);
mediaEncoder.SetAvailableEncoders(result.Item2);
});
}
/// <summary>

View File

@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case OperatingSystem.Linux:
info.ArchiveType = "7z";
info.Version = "20150717";
info.Version = "20150917";
break;
case OperatingSystem.Osx:
@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
switch (environment.SystemArchitecture)
{
case Architecture.X86_X64:
info.Version = "20150827";
info.Version = "20150917";
break;
case Architecture.X86:
info.Version = "20150110";
@ -54,7 +54,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
info.FFMpegFilename = "ffmpeg.exe";
info.FFProbeFilename = "ffprobe.exe";
info.Version = "20150717";
info.Version = "20150916";
info.ArchiveType = "7z";
switch (environment.SystemArchitecture)
@ -83,14 +83,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
"http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150717-git-8250943-win64-static.7z",
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win64-static.7z"
"http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150916-git-cbbd906-win64-static.7z",
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150916-git-cbbd906-win64-static.7z"
};
case Architecture.X86:
return new[]
{
"http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150717-git-8250943-win32-static.7z",
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win32-static.7z"
"http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150916-git-cbbd906-win32-static.7z",
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150916-git-cbbd906-win32-static.7z"
};
}
break;
@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.7.2.7z"
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.0.7z"
};
case Architecture.X86:
return new[]
@ -119,12 +119,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-64bit-static.7z"
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.8.0-64bit-static.7z"
};
case Architecture.X86:
return new[]
{
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-32bit-static.7z"
"https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.8.0-32bit-static.7z"
};
}
break;

View File

@ -7,6 +7,7 @@ using System.Globalization;
using System.IO;
using System.Text;
using MediaBrowser.Common.IO;
using System.Collections.Generic;
namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
@ -23,71 +24,65 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
_fileSystem = fileSystem;
}
public void Validate(FFMpegInfo info)
public Tuple<List<string>,List<string>> Validate(FFMpegInfo info)
{
_logger.Info("FFMpeg: {0}", info.EncoderPath);
_logger.Info("FFProbe: {0}", info.ProbePath);
string cacheKey;
var decoders = GetDecoders(info.EncoderPath);
var encoders = GetEncoders(info.EncoderPath);
return new Tuple<List<string>, List<string>>(decoders, encoders);
}
private List<string> GetDecoders(string ffmpegPath)
{
string output = string.Empty;
try
{
cacheKey = new FileInfo(info.EncoderPath).Length.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
}
catch (IOException)
{
// This could happen if ffmpeg is coming from a Path variable and we don't have the full path
cacheKey = Guid.NewGuid().ToString("N");
output = GetFFMpegOutput(ffmpegPath, "-decoders");
}
catch
{
cacheKey = Guid.NewGuid().ToString("N");
}
var cachePath = Path.Combine(_appPaths.CachePath, "1" + cacheKey);
var found = new List<string>();
var required = new[]
{
"h264_qsv",
"mpeg2_qsv",
"vc1_qsv"
};
ValidateCodecs(info.EncoderPath, cachePath);
foreach (var codec in required)
{
var srch = " " + codec + " ";
if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
{
_logger.Warn("ffmpeg is missing decoder " + codec);
}
else
{
found.Add(codec);
}
}
return found;
}
private void ValidateCodecs(string ffmpegPath, string cachePath)
private List<string> GetEncoders(string ffmpegPath)
{
string output = null;
try
{
output = _fileSystem.ReadAllText(cachePath, Encoding.UTF8);
output = GetFFMpegOutput(ffmpegPath, "-encoders");
}
catch
{
}
if (string.IsNullOrWhiteSpace(output))
{
try
{
output = GetFFMpegOutput(ffmpegPath, "-encoders");
}
catch
{
return;
}
try
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(cachePath));
_fileSystem.WriteAllText(cachePath, output, Encoding.UTF8);
}
catch
{
}
}
ValidateCodecsFromOutput(output);
}
private void ValidateCodecsFromOutput(string output)
{
var found = new List<string>();
var required = new[]
{
"libx264",
@ -103,16 +98,21 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
"srt"
};
foreach (var encoder in required)
foreach (var codec in required)
{
var srch = " " + encoder + " ";
var srch = " " + codec + " ";
if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
{
_logger.Error("ffmpeg is missing encoder " + encoder);
//throw new ArgumentException("ffmpeg is missing encoder " + encoder);
_logger.Warn("ffmpeg is missing encoder " + codec);
}
else
{
found.Add(codec);
}
}
return found;
}
private string GetFFMpegOutput(string path, string arguments)