diff --git a/MediaBrowser.Controller/FFMpeg/FFProbe.cs b/MediaBrowser.Controller/FFMpeg/FFProbe.cs new file mode 100644 index 0000000000..efd5491de0 --- /dev/null +++ b/MediaBrowser.Controller/FFMpeg/FFProbe.cs @@ -0,0 +1,68 @@ +using System; +using System.Diagnostics; +using MediaBrowser.Common.Logging; +using MediaBrowser.Common.Serialization; + +namespace MediaBrowser.Controller.FFMpeg +{ + public static class FFProbe + { + public static FFProbeResult Run(string path) + { + ProcessStartInfo startInfo = new ProcessStartInfo(); + + startInfo.CreateNoWindow = true; + + startInfo.UseShellExecute = false; + + // Must consume both or ffmpeg may hang due to deadlocks. See comments below. + startInfo.RedirectStandardOutput = true; + startInfo.RedirectStandardError = true; + + startInfo.FileName = Kernel.Instance.ApplicationPaths.FFProbePath; + startInfo.WorkingDirectory = Kernel.Instance.ApplicationPaths.FFMpegDirectory; + startInfo.Arguments = string.Format("\"{0}\" -v quiet -print_format json -show_streams -show_format", path); + + Logger.LogInfo(startInfo.FileName + " " + startInfo.Arguments); + + Process process = new Process(); + process.StartInfo = startInfo; + + try + { + process.Start(); + + // MUST read both stdout and stderr asynchronously or a deadlock may occurr + // If we ever decide to disable the ffmpeg log then you must uncomment the below line. + process.BeginErrorReadLine(); + + FFProbeResult result = JsonSerializer.DeserializeFromStream(process.StandardOutput.BaseStream); + + process.WaitForExit(); + + Logger.LogInfo("FFMpeg exited with code " + process.ExitCode); + + return result; + } + catch (Exception ex) + { + Logger.LogException(ex); + + // Hate having to do this + try + { + process.Kill(); + } + catch + { + } + + return null; + } + finally + { + process.Dispose(); + } + } + } +} diff --git a/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs b/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs new file mode 100644 index 0000000000..cc449991de --- /dev/null +++ b/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.FFMpeg +{ + /// + /// Provides a class that we can use to deserialize the ffprobe json output + /// Sample output: + /// http://stackoverflow.com/questions/7708373/get-ffmpeg-information-in-friendly-way + /// + public class FFProbeResult + { + public IEnumerable streams { get; set; } + public MediaFormat format { get; set; } + } + + public class MediaStream + { + public int index { get; set; } + public string profile { get; set; } + public string codec_name { get; set; } + public string codec_long_name { get; set; } + public string codec_type { get; set; } + public string codec_time_base { get; set; } + public string codec_tag { get; set; } + public string codec_tag_string { get; set; } + public string sample_fmt { get; set; } + public string sample_rate { get; set; } + public int channels { get; set; } + public int bits_per_sample { get; set; } + public string r_frame_rate { get; set; } + public string avg_frame_rate { get; set; } + public string time_base { get; set; } + public string start_time { get; set; } + public string duration { get; set; } + public string bit_rate { get; set; } + + public int width { get; set; } + public int height { get; set; } + public int has_b_frames { get; set; } + public string sample_aspect_ratio { get; set; } + public string display_aspect_ratio { get; set; } + public string pix_fmt { get; set; } + public int level { get; set; } + public MediaTags tags { get; set; } + } + + public class MediaFormat + { + public string filename { get; set; } + public int nb_streams { get; set; } + public string format_name { get; set; } + public string format_long_name { get; set; } + public string start_time { get; set; } + public string duration { get; set; } + public string size { get; set; } + public string bit_rate { get; set; } + public MediaTags tags { get; set; } + } + + public class MediaTags + { + public string title { get; set; } + public string comment { get; set; } + public string artist { get; set; } + public string album { get; set; } + public string album_artist { get; set; } + public string composer { get; set; } + public string copyright { get; set; } + public string publisher { get; set; } + public string track { get; set; } + public string disc { get; set; } + public string genre { get; set; } + public string date { get; set; } + public string language { get; set; } + } +} diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index a9e536c7bd..21405e5727 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; -using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Kernel; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Events; diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 580b4d7b56..048f6993b4 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -52,6 +52,8 @@ + +