Explorar el Código

ffmpeg chmod +x if needed

Krzysztof Krysiński hace 7 meses
padre
commit
167383ea18

+ 46 - 10
src/PixiEditor.AnimationRenderer.FFmpeg/FFMpegRenderer.cs

@@ -1,4 +1,5 @@
-using System.Drawing;
+using System.Diagnostics;
+using System.Drawing;
 using System.Reflection;
 using FFMpegCore;
 using FFMpegCore.Arguments;
@@ -22,10 +23,16 @@ public class FFMpegRenderer : IAnimationRenderer
     {
         string path = $"ThirdParty/{IOperatingSystem.Current.Name}/ffmpeg";
 
-        GlobalFFOptions.Configure(new FFOptions()
+        string binaryPath = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), path);
+
+        GlobalFFOptions.Configure(new FFOptions() { BinaryFolder = binaryPath });
+
+        if (IOperatingSystem.Current.IsUnix)
         {
-            BinaryFolder = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), path),
-        });
+            MakeExecutableIfNeeded(binaryPath);
+        }
+
+        string paletteTempPath = Path.Combine(Path.GetDirectoryName(outputPath), "RenderTemp", "palette.png");
 
         try
         {
@@ -38,7 +45,6 @@ public class FFMpegRenderer : IAnimationRenderer
 
             RawVideoPipeSource streamPipeSource = new(frames) { FrameRate = FrameRate, };
 
-            string paletteTempPath = Path.Combine(Path.GetDirectoryName(outputPath), "RenderTemp", "palette.png");
 
             if (!Directory.Exists(Path.GetDirectoryName(paletteTempPath)))
             {
@@ -63,20 +69,50 @@ public class FFMpegRenderer : IAnimationRenderer
             var result = await outputArgs.CancellableThrough(cancellationToken)
                 .NotifyOnProgress(progressCallback, totalTimeSpan).ProcessAsynchronously();
 
-            if (RequiresPaletteGeneration())
+            DisposeStream(frames);
+
+            return result;
+        }
+        finally
+        {
+            if (RequiresPaletteGeneration() && File.Exists(paletteTempPath))
             {
                 File.Delete(paletteTempPath);
                 Directory.Delete(Path.GetDirectoryName(paletteTempPath));
             }
+        }
+    }
 
-            DisposeStream(frames);
+    private static void MakeExecutableIfNeeded(string binaryPath)
+    {
+        string filePath = Path.Combine(binaryPath, "ffmpeg");
 
-            return result;
+        if (!File.Exists(filePath))
+        {
+            throw new FileNotFoundException("FFmpeg binary not found");
+        }
+
+        try
+        {
+            var process = IOperatingSystem.Current.ProcessUtility.Execute($"{filePath}", "-version");
+
+            bool exited = process.WaitForExit(500);
+
+            if (!exited)
+            {
+                throw new InvalidOperationException("Failed to perform FFmpeg check");
+            }
+
+            if (process.ExitCode == 0)
+            {
+                return;
+            }
+
+            IOperatingSystem.Current.ProcessUtility.Execute("chmod", $"+x {filePath}");
         }
         catch (Exception e)
         {
-            Console.WriteLine(e);
-            return false;
+            IOperatingSystem.Current.ProcessUtility.Execute("chmod", $"+x {filePath}");
         }
     }
 

+ 1 - 0
src/PixiEditor.AnimationRenderer.FFmpeg/PixiEditor.AnimationRenderer.FFmpeg.csproj

@@ -6,6 +6,7 @@
     <Nullable>enable</Nullable>
     <Configurations>Release;Debug</Configurations>
     <Platforms>arm64;x64</Platforms>
+    <RuntimeIdentifiers>win-x64;win-arm64;osx-x64;osx-arm64;linux-x64;linux-arm64</RuntimeIdentifiers>
   </PropertyGroup>
 
   <ItemGroup>

+ 26 - 9
src/PixiEditor.MacOs/MacOsProcessUtility.cs

@@ -35,24 +35,41 @@ internal class MacOsProcessUtility : IProcessUtility
         return Environment.IsPrivilegedProcess;
     }
 
-    public static void ShellExecute(string url)
+    public static Process ShellExecute(string url)
     {
-        Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true, });
+        return Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true, });
     }
 
-    void IProcessUtility.ShellExecute(string url)
+    Process IProcessUtility.ShellExecute(string url)
     {
-        ShellExecute(url);
+        return ShellExecute(url);
     }
-    
-    void IProcessUtility.ShellExecute(string url, string args)
+
+    Process IProcessUtility.ShellExecute(string url, string args)
     {
-        ShellExecute(url, args);
+        return ShellExecute(url, args);
+    }
+
+    Process IProcessUtility.Execute(string path, string args)
+    {
+        return Execute(path, args);
+    }
+
+    public static Process Execute(string path, string args)
+    {
+        return Process.Start(new ProcessStartInfo
+        {
+            FileName = path,
+            Arguments = args,
+            UseShellExecute = false,
+            RedirectStandardOutput = true,
+            RedirectStandardError = true,
+        });
     }
 
-    public static void ShellExecute(string url, string args)
+    public static Process ShellExecute(string url, string args)
     {
-        Process.Start(new ProcessStartInfo { FileName = url, Arguments = args, UseShellExecute = true, });
+        return Process.Start(new ProcessStartInfo { FileName = url, Arguments = args, UseShellExecute = true });
     }
 
     public static void ShellExecuteEV(string path) => ShellExecute(Environment.ExpandEnvironmentVariables(path));

+ 1 - 0
src/PixiEditor.OperatingSystem/IOperatingSystem.cs

@@ -18,6 +18,7 @@ public interface IOperatingSystem
     public bool IsLinux => Name == "Linux";
     public bool IsMiscellaneous => !IsMacOs && !IsWindows && !IsLinux;
     public string ExecutableExtension { get; }
+    public bool IsUnix => IsMacOs || IsLinux;
 
     public static void RegisterOS(IOperatingSystem operatingSystem)
     {

+ 3 - 2
src/PixiEditor.OperatingSystem/IProcessUtility.cs

@@ -7,6 +7,7 @@ public interface IProcessUtility
     public Process RunAsAdmin(string path);
     public Process RunAsAdmin(string path, bool createWindow);
     public bool IsRunningAsAdministrator();
-    public void ShellExecute(string toExecute);
-    public void ShellExecute(string toExecute, string args);
+    public Process ShellExecute(string toExecute);
+    public Process ShellExecute(string toExecute, string args);
+    public Process Execute(string path, string args);
 }

+ 26 - 8
src/PixiEditor.Windows/WindowsProcessUtility.cs

@@ -37,28 +37,46 @@ public class WindowsProcessUtility : IProcessUtility
         return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
     }
 
-    public static void ShellExecute(string url)
+    public static Process ShellExecute(string url)
     {
-        Process.Start(new ProcessStartInfo
+        return Process.Start(new ProcessStartInfo
         {
             FileName = url,
             UseShellExecute = true,
         });
     }
 
-    void IProcessUtility.ShellExecute(string url)
+    Process IProcessUtility.ShellExecute(string url)
     {
-        ShellExecute(url);
+        return ShellExecute(url);
     }
     
-    void IProcessUtility.ShellExecute(string url, string args)
+    Process IProcessUtility.ShellExecute(string url, string args)
     {
-        ShellExecute(url, args);
+        return ShellExecute(url, args);
     }
 
-    public static void ShellExecute(string url, string args)
+
+    Process IProcessUtility.Execute(string path, string args)
+    {
+        return Execute(path, args);
+    }
+    
+    public static Process Execute(string path, string args)
+    {
+        return Process.Start(new ProcessStartInfo
+        {
+            FileName = path,
+            Arguments = args,
+            UseShellExecute = false,
+            RedirectStandardOutput = true,
+            RedirectStandardError = true,
+        });
+    }
+
+    public static Process ShellExecute(string url, string args)
     {
-        Process.Start(new ProcessStartInfo
+        return Process.Start(new ProcessStartInfo
         {
             FileName = url,
             Arguments = args,