added setting for intel qsv hardware decoding
This commit is contained in:
parent
2acd1665c9
commit
5340bfe8da
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateCodecs(string ffmpegPath, string cachePath)
|
||||
return found;
|
||||
}
|
||||
|
||||
private List<string> GetEncoders(string ffmpegPath)
|
||||
{
|
||||
string output = null;
|
||||
try
|
||||
{
|
||||
output = _fileSystem.ReadAllText(cachePath, Encoding.UTF8);
|
||||
}
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user