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