[chronojump] Added ffmpegCapture standalone program to test on all systems



commit e67233829a32a258e2324741b47f71fd839cc5f3
Author: Xavier de Blas <xaviblas gmail com>
Date:   Mon Oct 15 19:57:43 2018 +0200

    Added ffmpegCapture standalone program to test on all systems

 testing-stuff/ffmpegCapture/commandLineEncoder.cs | 102 ++++++
 testing-stuff/ffmpegCapture/compile.sh            |   1 +
 testing-stuff/ffmpegCapture/constants.cs          |  38 +++
 testing-stuff/ffmpegCapture/executeProcess.cs     | 292 ++++++++++++++++
 testing-stuff/ffmpegCapture/ffmpegCapture.exe     | Bin 0 -> 17920 bytes
 testing-stuff/ffmpegCapture/main.cs               | 398 ++++++++++++++++++++++
 testing-stuff/ffmpegCapture/util.cs               | 133 ++++++++
 testing-stuff/ffmpegCapture/utilAll.cs            | 134 ++++++++
 testing-stuff/ffmpegCapture/utilMultimedia.cs     | 100 ++++++
 9 files changed, 1198 insertions(+)
---
diff --git a/testing-stuff/ffmpegCapture/commandLineEncoder.cs 
b/testing-stuff/ffmpegCapture/commandLineEncoder.cs
new file mode 100644
index 00000000..af2b81c2
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/commandLineEncoder.cs
@@ -0,0 +1,102 @@
+// This file is copied and adapted from 
https://raw.githubusercontent.com/ericpopivker/Command-Line-Encoder/master/CommandLineEncoder/CommandLineEncoder/Utils.cs
+
+using System;
+using System.Text.RegularExpressions;
+
+public class CommandLineEncoder
+{
+               private const string EscapedSlashN = "[SlashN]";
+
+               public static string EncodeArgText(string original)
+               {
+                       var result = original;
+                       result = TryEncodeNewLine(result);
+                       result = TryEncodeSlashesFollowedByQuotes(result);
+                       result = TryEncodeQuotes(result);
+                       result = TryEncodeLastSlash(result);
+                       return "\"" + result + "\"";
+               }
+
+               private static string TryEncodeNewLine(string original)
+               {
+                       var result = original.Replace("\\n", EscapedSlashN);
+
+                       result = result.Replace(Environment.NewLine, "\\n");
+                       return result;
+               }
+
+               private static string TryEncodeSlashesFollowedByQuotes(string original)
+               {
+                       var regexPattern = @"\\+""";
+
+                       string result = Regex.Replace(original, regexPattern,
+                               delegate(Match match)
+                               {
+                                       string matchText = match.ToString();
+                                       string justSlashes = matchText.Remove(matchText.Length - 1);
+                                       return justSlashes + justSlashes + "\"";  //double up the slashes
+                               });
+
+                       return result;
+               }
+
+               private static string TryEncodeQuotes(string original)
+               {
+                       var result = original.Replace("\"", "\"\"");
+                       return result;
+               }
+
+               private static string TryEncodeLastSlash(string original)
+               {
+                       var regexPattern = @"\\+$";
+
+                       string result = Regex.Replace(original, regexPattern,
+                               delegate(Match match)
+                               {
+                                       string matchText = match.ToString();
+                                       return matchText + matchText;  //double up the slashes
+                               });
+
+                       return result;
+               }
+
+               public static string DecodeArgText(string original)
+               {
+                       string decoded = original;
+
+                       decoded = TryDecodeNewLine(decoded);
+
+                       return decoded;
+               }
+
+
+               private static string TryDecodeNewLine(string original)
+               {
+                       var result = original.Replace("\\n", Environment.NewLine);
+
+                       result = result.Replace(EscapedSlashN, "\\n");
+
+                       return result;
+               }
+
+
+
+               public static string EscapeBackSlashes(string text)
+               {
+                       var regexPattern = "\\\\";
+                       var result = text;
+                       var regex = new Regex(regexPattern);
+                       var matches = regex.Matches(text);
+
+                       for (int i = matches.Count - 1; i >= 0; i--)
+                       {
+                               var match = matches[i];
+                               var index = match.Index + match.Length;
+
+                               if (index >= text.Length || text[index] == '\\')
+                                       result = result.Insert(match.Index, "\\");
+                       }
+
+                       return result;
+               }
+}
diff --git a/testing-stuff/ffmpegCapture/compile.sh b/testing-stuff/ffmpegCapture/compile.sh
new file mode 100755
index 00000000..b8eb3c77
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/compile.sh
@@ -0,0 +1 @@
+mcs *.cs -out:ffmpegCapture.exe
diff --git a/testing-stuff/ffmpegCapture/constants.cs b/testing-stuff/ffmpegCapture/constants.cs
new file mode 100644
index 00000000..9435a4db
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/constants.cs
@@ -0,0 +1,38 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2004-2017   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System;
+//do not use gtk or gdk because this class is used by the server
+//see UtilGtk for eg color definitions
+
+public class Constants
+{
+       public enum TestTypes { JUMP, JUMP_RJ, RUN, RUN_I, RT, PULSE, MULTICHRONOPIC, ENCODER }
+        public static string FileCopyProblem = "Error. Cannot copy file.";
+        public static string FileCannotSave = "Error. File cannot be saved.";
+        public static string VideoTemp = "chronojump-last-video";
+        public enum MultimediaItems {
+                PHOTO, PHOTOPNG, VIDEO
+        }   
+
+       public const string ExtensionPhoto = ".jpg";
+        public const string ExtensionPhotoPng = ".png"; //used for Cairo resized images
+        public const string ExtensionVideo = ".mp4";
+}
diff --git a/testing-stuff/ffmpegCapture/executeProcess.cs b/testing-stuff/ffmpegCapture/executeProcess.cs
new file mode 100644
index 00000000..e0305286
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/executeProcess.cs
@@ -0,0 +1,292 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or   
+ * (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) 2016-2017   Carles Pina i Estany <carles pina cat>
+ * Copyright (C) 2017   Xavier de Blas <xaviblas gmail com>
+ */
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System;
+using System.IO;                //FILE
+
+
+/* This class executes a process and returns the result. */
+class ExecuteProcess
+{
+       public struct Result
+       {
+               public const int ERROR_CANT_START = -1;
+
+               // Encapsulates the result of a run: stdout, stderr, exitCode if process couldn't start is 
ERROR_CANT_START),
+               // success (if exitCode != 0) and errorMessage to be shown to the user.
+               public string stdout;
+               public string stderr;
+               public string allOutput;
+
+               public int exitCode;
+               public bool success;
+               public string errorMessage;
+
+               public Result(string stdout, string stderr, int exitCode, string errorMessage = "")
+               {
+                       this.stdout = stdout;
+                       this.stderr = stderr;
+                       this.allOutput = stdout + stderr;
+                       this.exitCode = exitCode;
+                       this.success = (exitCode == 0);
+                       this.errorMessage = errorMessage;
+               }
+       };
+
+       public static Result runShowErrorIfNotStarted(string file_name, List<string> parameters)
+       {
+               Result result = run(file_name, parameters);
+
+               if (result.exitCode == Result.ERROR_CANT_START) {
+                       //new DialogMessage (Constants.MessageTypes.WARNING, result.errorMessage);
+                       Console.WriteLine(result.errorMessage);
+               }
+
+               return result;
+       }
+
+       public static Result run(string file_name)
+       {
+               return runDo (file_name, new List<string>());
+       }
+       public static Result run(string file_name, List<string> parameters)
+       {
+               return runDo (file_name, parameters);
+       }
+
+       // Executes file_name without creating a Window and without using the shell
+       // with the parameters. Waits that it finishes it. Returns the stdout and stderr.
+       private static Result runDo(string file_name, List<string> parameters)
+       {
+               Process process = new Process();
+               ProcessStartInfo processStartInfo = new ProcessStartInfo();
+
+               processStartInfo.FileName = file_name;
+
+               string parameters_string = "";
+               foreach (string parameter in parameters)
+               {
+                       parameters_string += CommandLineEncoder.EncodeArgText (parameter) + " ";
+               }
+
+               processStartInfo.Arguments = parameters_string;
+
+               Console.WriteLine ("ExecuteProcess FileName: " + processStartInfo.FileName);
+               Console.WriteLine ("ExecuteProcess Arguments: " + processStartInfo.Arguments);
+
+               processStartInfo.CreateNoWindow = true;
+               processStartInfo.UseShellExecute = false;
+               processStartInfo.RedirectStandardInput = false;
+               processStartInfo.RedirectStandardError = true;
+               processStartInfo.RedirectStandardOutput = true;
+
+               process.StartInfo = processStartInfo;
+
+               try {
+                       process.Start();
+               }
+               catch(Exception e) {
+                       string errorMessage = String.Format ("Cannot start:\n" +
+                                                                              "{0}\n" +
+                                                                              "with the parameters:" +
+                                                                              "{1}\n" +
+                                                                              "Exception:\n" +
+                                                                              "{2}",
+                                                            processStartInfo.FileName, parameters_string, 
e.Message);
+                       Console.WriteLine (errorMessage);
+                       return new Result ("", "", Result.ERROR_CANT_START, errorMessage);
+               }
+
+               string stdout = process.StandardOutput.ReadToEnd().TrimEnd ('\n');
+               string stderr = process.StandardError.ReadToEnd ().TrimEnd ('\n');
+
+               process.WaitForExit ();
+
+               if (stderr != "") {
+                       Console.WriteLine(String.Format("Executed: {0} Parameters: {1} Stdout: {2} Stderr: 
{3}", processStartInfo.FileName, parameters_string, stdout, stderr));
+               }
+
+               int exitCode = process.ExitCode;
+
+               return new Result (stdout, stderr, exitCode);
+       }
+
+       /*
+        * run a process on the background, eg: read rfid.
+        * don't call WaitForExit(), kill it on Chronojump exit
+        * returns false if there are problems calling it
+        */
+       public static bool RunAtBackground(ref Process process, string file_name, List<string> parameters, 
bool redirectInput)
+       {
+               ProcessStartInfo processStartInfo = new ProcessStartInfo();
+
+               processStartInfo.FileName = file_name;
+
+               string parameters_string = "";
+               foreach (string parameter in parameters)
+               {
+                       parameters_string += CommandLineEncoder.EncodeArgText (parameter) + " ";
+               }
+
+               processStartInfo.Arguments = parameters_string;
+
+               Console.WriteLine ("ExecuteProcess FileName: " + processStartInfo.FileName);
+               Console.WriteLine ("ExecuteProcess Arguments: " + processStartInfo.Arguments);
+
+               processStartInfo.CreateNoWindow = true;
+               processStartInfo.UseShellExecute = false;
+               processStartInfo.RedirectStandardInput = redirectInput; //note UseShellExecute has to be 
false to be able to redirect
+               processStartInfo.RedirectStandardError = true;
+               processStartInfo.RedirectStandardOutput = true;
+
+               process.StartInfo = processStartInfo;
+
+               try {
+                       process.Start();
+               }
+               catch(Exception e) {
+                       string errorMessage = String.Format ("Cannot start:\n" +
+                                                                              "{0}\n" +
+                                                                              "with the parameters:" +
+                                                                              "{1}\n" +
+                                                                              "Exception:\n" +
+                                                                              "{2}",
+                                                            processStartInfo.FileName, parameters_string, 
e.Message);
+                       Console.WriteLine (errorMessage);
+                       return false;
+               }
+
+               return true;
+       }
+
+
+       //better method than below
+       //https://stackoverflow.com/a/262291
+       public static bool IsRunning2 (Process process, string executable)
+       {
+               Process[] pNameArray = Process.GetProcessesByName(process.ProcessName);
+               if (pNameArray.Length == 0)
+                       return false;
+
+               foreach(Process p in pNameArray)
+                       if(p.Id == process.Id)
+                               return true;
+
+               return false;
+       }
+
+       //This seems is not working with ffmpeg capture, try method obove
+       public static bool IsRunning(Process process)
+       {
+               Console.WriteLine("calling Process.IsRunning()");
+               if(process == null) {
+                       Console.WriteLine("process == null");
+                       return false;
+               } else {
+                       if(isRunningThisProcess(process))
+                               return true;
+               }
+
+               return false;
+       }
+
+       private static bool isRunningThisProcess(Process p)
+       {
+               /*
+                * Process Id is not valid if the associated process is not running.
+                * Need to ensure that the process is running before attempting to retrieve the Id property.
+                */
+
+               try {
+                       Console.WriteLine(string.Format("last pid id {0}", p.Id));
+                       Process pid = Process.GetProcessById(p.Id);
+                       if(pid == null)
+                               return false;
+               } catch {
+                       return false;
+               }
+
+               return true;
+       }
+
+       /*
+        * don't use this because in linux R script can be called by:
+        * "/usr/lib/R/bin/exec/R"
+        * and it will not be found passing "R" or "*R"
+       private bool isRunningThisProcess(string name)
+       {
+               Process [] pids = Process.GetProcessesByName(name);
+               foreach (Process myPid in pids) {
+                       Console.WriteLine(string.Format("pids id: {0}", myPid.Id));
+                       if (myPid.Id == Convert.ToInt32(p.Id))
+                               return true;
+               }
+
+               return false;
+       }
+       */
+
+       /*
+        * The process.Responding only works on GUI processes
+        * So, here we send a "ping" expecting to see the result in short time
+        *
+        * TODO: maybe is good to kill the unresponsive processes
+        */
+       public static bool IsResponsive(Process p)
+       {
+               Random rnd = new Random();
+               int randomInt = rnd.Next(); //eg. 1234
+
+               string randomPingStr = "PING" + Path.Combine(Path.GetTempPath(), "chronojump" + 
randomInt.ToString() + ".txt"); 
+               //eg Linux: 'PING/tmp/chronojump1234.txt'
+               //eg Windows: 'PINGC:\Temp...\chronojump1234.txt'
+
+               if (UtilAll.IsWindows()) {
+                       //On win32 R understands backlash as an escape character and
+                       //a file path uses Unix-like path separator '/'
+                       randomPingStr = randomPingStr.Replace("\\","/");
+               }
+               //eg Windows: 'PINGC:/Temp.../chronojump1234.txt'
+
+               Console.WriteLine("Sending ping: " + randomPingStr);
+               try {
+                       p.StandardInput.WriteLine(randomPingStr);
+               } catch {
+                       Console.WriteLine("Catched waiting response");
+                       return false;
+               }
+
+               //wait 250ms the response
+               System.Threading.Thread.Sleep(250);
+
+               //On Linux will be '/' on Windows '\'
+               if(File.Exists(Path.Combine(Path.GetTempPath(), "chronojump" + randomInt.ToString() + 
".txt"))) {
+                       Console.WriteLine("Process is responding");
+                       return true;
+               }
+
+               Console.WriteLine("Process is NOT responding");
+               return false;
+       }
+
+}
diff --git a/testing-stuff/ffmpegCapture/ffmpegCapture.exe b/testing-stuff/ffmpegCapture/ffmpegCapture.exe
new file mode 100755
index 00000000..1e90a6cd
Binary files /dev/null and b/testing-stuff/ffmpegCapture/ffmpegCapture.exe differ
diff --git a/testing-stuff/ffmpegCapture/main.cs b/testing-stuff/ffmpegCapture/main.cs
new file mode 100644
index 00000000..eb35de53
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/main.cs
@@ -0,0 +1,398 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or   
+ * (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2018   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System.Collections.Generic; //List
+using System.Diagnostics;
+using System;
+using System.IO;
+using System.Text.RegularExpressions; //Regex
+
+class FfmpegCapture
+{
+       private UtilAll.OperatingSystems os;
+       private string captureExecutable = "ffmpeg";
+        private StreamWriter streamWriter;
+       private Process process;
+       protected static internal string programFfmpegNotInstalled =
+               string.Format("Error. {0} is not installed.", "ffmpeg");
+       public bool Running;
+        private string videoDevice;
+
+
+
+
+       /*
+       public void WebcamFfmpeg (UtilAll.OperatingSystems os, string videoDevice)
+       {
+               this.os = os;
+               this.videoDevice = videoDevice;
+
+               captureExecutable = "ffmpeg";
+               if(os == UtilAll.OperatingSystems.WINDOWS)
+                       captureExecutable = System.IO.Path.Combine(Util.GetPrefixDir(), "bin/ffmpeg.exe");
+
+               Running = false;
+       }
+       */
+
+       /*
+        * constructor for Play
+
+       public WebcamFfmpeg ()
+       {
+       }
+        */
+
+               // Result struct holds the output, error and success operations. It's used to pass
+        // errors from different layers (e.g. executing Python scripts) to the UI layer
+        public struct Result
+        {
+                public bool success;
+                public string output;
+                public string error;
+
+                public Result(bool success, string output, string error = "")
+                {
+                        this.success = success;
+                        this.output = output;
+                        this.error = error;
+                }
+        }
+
+        public enum CaptureTypes { PHOTO, VIDEO }
+
+       public Result CapturePrepare (CaptureTypes captureType)
+       {
+               if(process != null)
+                       return new Result (false, "");
+
+               return new Result (true, "");
+       }
+
+       public Result Play(string filename)
+       {
+               //only implemented on mplayer
+               return new Result (true, "");
+       }
+       public bool Snapshot()
+       {
+               //only implemented on mplayer
+               return true;
+       }
+
+
+       public static void Main(string[] args)
+       {
+               new FfmpegCapture(args);
+       }
+
+       public FfmpegCapture(string[] args)
+       {
+               if(args.Length != 1) {
+                       Console.WriteLine("Need to pass the videoDevice");
+                       return;
+               }
+
+                os = UtilAll.GetOSEnum();
+               videoDevice = args[0];
+
+               if(os == UtilAll.OperatingSystems.WINDOWS)
+                       captureExecutable = System.IO.Path.Combine(Util.GetPrefixDir(), "bin/ffmpeg.exe");
+
+               process = new Process();
+               List<string> parameters = createParametersOnlyCapture();
+               //List<string> parameters = createParametersCaptureAndDelayedView();
+               bool success = ExecuteProcess.RunAtBackground (ref process, captureExecutable, parameters, 
true); //redirectInput
+               if(! success)
+               {
+                       streamWriter = null;
+                       process = null;
+                       //return new Result (false, "", programFfmpegNotInstalled);
+                       return;
+               }
+
+               streamWriter = process.StandardInput;
+               Running = true;
+
+               Console.WriteLine("Recording 5 seconds ...");
+               for(int countA = 4; countA >= 0; countA --)
+               {
+                       System.Threading.Thread.Sleep(1000);
+                       Console.WriteLine(countA.ToString());
+               }
+       
+               ExitAndFinish (0, Constants.TestTypes.RUN, 1);
+
+
+               //return new Result (true, "");
+       }
+
+       private List<string> createParametersOnlyCapture()
+       {
+               // ffmpeg -y -f v4l2 -framerate 30 -video_size 640x480 -input_format mjpeg -i /dev/video0 
out.mp4
+               List<string> parameters = new List<string>();
+
+               int i = 0;
+               parameters.Insert (i ++, "-y"); //overwrite
+
+               parameters.Insert (i ++, "-f");
+               if(os == UtilAll.OperatingSystems.LINUX)
+                       parameters.Insert (i ++, "v4l2");
+               else //windows
+                       parameters.Insert (i ++, "dshow");
+
+               parameters.Insert (i ++, "-framerate");
+               parameters.Insert (i ++, "30");
+               parameters.Insert (i ++, "-video_size");
+               parameters.Insert (i ++, "640x480");
+
+               if(os == UtilAll.OperatingSystems.LINUX) {
+                       parameters.Insert (i ++, "-input_format");
+                       parameters.Insert (i ++, "mjpeg");
+               }
+
+               parameters.Insert (i ++, "-i");
+               if(os == UtilAll.OperatingSystems.LINUX)
+                       parameters.Insert (i ++, videoDevice);
+               else //windows
+                       parameters.Insert (i ++, "video=" + videoDevice);
+
+               parameters.Insert (i ++, Util.GetVideoTempFileName());
+
+               return parameters;
+       }
+
+       //Care: press q two times, one for each process on the tee
+       //or only one on the ffplay process
+       private List<string> createParametersCaptureAndDelayedView()
+       {
+               //ffmpeg -y -f v4l2 -i /dev/video0 -map 0 -c:v libx264 -f tee "output.mkv|[f=nut]pipe:" | 
ffplay pipe:
+               List<string> parameters = new List<string>();
+
+               int i = 0;
+               parameters.Insert (i ++, "-y"); //overwrite
+
+               parameters.Insert (i ++, "-f");
+               if(os == UtilAll.OperatingSystems.LINUX)
+                       parameters.Insert (i ++, "v4l2");
+               else //windows
+                       parameters.Insert (i ++, "dshow");
+
+               parameters.Insert (i ++, "-i");
+               if(os == UtilAll.OperatingSystems.LINUX)
+                       parameters.Insert (i ++, "\"" + videoDevice + "\"");
+               else //windows
+                       parameters.Insert (i ++, "video=\"" + videoDevice + "\"");
+
+               parameters.Insert (i ++, "-map");
+               parameters.Insert (i ++, "0");
+               parameters.Insert (i ++, "-c:v");
+               parameters.Insert (i ++, "libx264");
+               parameters.Insert (i ++, "-f");
+               parameters.Insert (i ++, "tee");
+
+               //TODO: Think on the \" for windows and maybe also for other OSes
+               parameters.Insert (i ++, "'" + Util.GetVideoTempFileName() + "|[f=nut]pipe:'");
+               parameters.Insert (i ++, "|");
+               parameters.Insert (i ++, "ffplay");
+               parameters.Insert (i ++, "pipe:");
+
+               return parameters;
+       }
+
+       /*
+        * there are problems calling the process with the "|"
+        * better call a shell script like this:
+        * ffmpeg_capture_and_play.sh
+        *
+        * #!/bin/bash
+        * ffmpeg -y -f v4l2 -i /dev/video0 -map 0 -c:v libx264 -f tee 
"/tmp/chronojump-last-video.mp4|[f=nut]pipe:" | ffplay pipe:
+        */
+
+
+       public Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID)
+       {
+               ExitCamera();
+
+               //Copy the video to expected place
+               //if (! Util.CopyTempVideo(sessionID, testType, testID))
+               //      return new Result (false, "", Constants.FileCopyProblem);
+
+               //Delete temp video
+               //deleteTempFiles();
+
+               return new Result (true, "");
+       }
+
+       public void ExitCamera()
+       {
+               Console.WriteLine("Exit camera");
+               Console.WriteLine("streamWriter is null: " + (streamWriter == null).ToString());
+               try {
+                       streamWriter.Write('q'); //encara que hi hagi el process.Close() de sota, no es tanca 
la càmera sense aquest 'q'
+                       //streamWriter.Flush();
+//                     streamWriter.WriteLine("\x3");
+                       //streamWriter.Flush();
+                       //process.StandardInput.WriteLine("\x3");
+//                     streamWriter.WriteLine("q\n");
+               } catch {
+                       //maybe Mplayer window has been closed by user
+                       process = null;
+                       Running = false;
+                       return;
+               }
+
+               Console.WriteLine("closing ...");
+               process.Close();
+
+               //this does not work
+               //Console.WriteLine("waiting for exit ...");
+               //process.WaitForExit();
+
+               Console.WriteLine("done!");
+
+               //amb el process.Close(); tanca i tanca be pero es perden fotogrames inicials i finals, vaja 
que no tanca massa be, no estic segur de si realment enviar la q serveix de algo, vaig a fer-ho sense la q
+               //si que tanca be pq ara he provat sense enviar el q, nomes amb el process.Close() i la 
camera es queda oberta
+
+               /*
+               //System.Threading.Thread.Sleep(500);
+               //better check if process still exists to later copy the video
+               do {
+                       Console.WriteLine("waiting 100 ms to end Ffmpeg");
+                       System.Threading.Thread.Sleep(100);
+               } while(ExecuteProcess.IsRunning2(process, captureExecutable));
+               */
+
+               streamWriter = null;
+               process = null;
+               Running = false;
+       }
+
+       /*
+        * protected methods
+        */
+
+       protected void deleteTempFiles()
+       {
+               Console.WriteLine("Deleting temp video");
+               if(File.Exists(Util.GetVideoTempFileName()))
+                       File.Delete(Util.GetVideoTempFileName());
+       }
+
+}
+
+public static class WebcamFfmpegGetDevicesWindows
+{
+        public static List<string> GetDevices()
+        {
+                string executable = "ffmpeg";
+                if(UtilAll.GetOSEnum() == UtilAll.OperatingSystems.WINDOWS)
+                        executable = System.IO.Path.Combine(Util.GetPrefixDir(), "bin/ffmpeg.exe");
+
+                List<string> parameters = createParameters();
+
+                ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, parameters);
+
+                Console.WriteLine("---- stdout: ----");
+                Console.WriteLine(execute_result.stdout);
+                Console.WriteLine("---- stderr: ----");
+                Console.WriteLine(execute_result.stderr);
+                Console.WriteLine("-----------------");
+
+                if(! execute_result.success)
+                {
+                        Console.WriteLine("WebcamFfmpegGetDevicesWindows error: " + execute_result.stderr);
+
+                        /*
+                         * on Windows the -i dummy produces an error, so stderr exists and success is false
+                         * stdout has the list of devices and stderr also
+                         * check if in stdout there's the: "DirectShow video devices" string and if not 
exists, really we have an error
+                         */
+                        if(execute_result.stdout != null && execute_result.stdout != "" &&
+                                        execute_result.stdout.Contains("DirectShow video devices"))
+                        {
+                                Console.WriteLine("Calling parse with stdout");
+                                return parse(execute_result.stdout);
+                        }
+
+                        if(execute_result.stderr != null && execute_result.stderr != "" &&
+                                        execute_result.stderr.Contains("DirectShow video devices"))
+                        {
+                                Console.WriteLine("Calling parse with stderr");
+                                return parse(execute_result.stderr);
+                        }
+
+                        return new List<string>();
+                }
+                else
+                        return parse(execute_result.stdout);
+        }
+
+        private static List<string> createParameters()
+        {
+                //ffmpeg -list_devices true -f dshow -i dummy
+                List<string> parameters = new List<string>();
+
+                int i = 0;
+                parameters.Insert (i ++, "-list_devices");
+                parameters.Insert (i ++, "true");
+                parameters.Insert (i ++, "-f");
+                parameters.Insert (i ++, "dshow");
+                parameters.Insert (i ++, "-i");
+                parameters.Insert (i ++, "dummy");
+
+                return parameters;
+        }
+
+        private static List<string> parse(string devicesOutput)
+        {
+                Console.WriteLine("Called parse");
+
+                /*
+                 * break the big string in \n strings
+                 * https://stackoverflow.com/a/1547483
+                 */
+                string[] lines = devicesOutput.Split(
+                                new[] { Environment.NewLine },
+                                StringSplitOptions.None
+                                );
+
+                List<string> parsedList = new List<string>();
+                foreach(string l in lines)
+                {
+                        Console.WriteLine("line: " + l);
+                        foreach(Match match in Regex.Matches(l, "\"([^\"]*)\""))
+                        {
+                                //remove quotes from the match (at beginning and end) to add it in SQL
+                                string s = match.ToString().Substring(1, match.ToString().Length -2);
+
+                                Console.WriteLine("add match: " + s);
+                                parsedList.Add(s);
+                        }
+
+                        //after the list of video devices comes the list of audio devices, skip it
+                        if(l.Contains("DirectShow audio devices"))
+                                break;
+                }
+
+                return parsedList;
+        }
+}
+
diff --git a/testing-stuff/ffmpegCapture/util.cs b/testing-stuff/ffmpegCapture/util.cs
new file mode 100644
index 00000000..b4786605
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/util.cs
@@ -0,0 +1,133 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2004-2017   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System;
+//using System.Data;
+using System.Text; //StringBuilder
+using System.Collections; //ArrayList
+using System.Collections.Generic; //List<T>
+using System.Diagnostics;      //for detect OS
+using System.IO;               //for detect OS
+using System.Globalization;    //Unicode
+
+//this class tries to be a space for methods that are used in different classes
+public class Util
+{
+       public static string GetManualDir() {
+               //we are on:
+               //lib/chronojump/ (Unix) or bin/ (win32)
+               //we have to go to
+               //share/doc/chronojump
+               return System.IO.Path.Combine(Util.GetPrefixDir(),
+                       "share" + Path.DirectorySeparatorChar + "doc" + Path.DirectorySeparatorChar + 
"chronojump");
+       }
+
+       public static string GetPrefixDir(){
+               string baseDirectory = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, 
"..");
+               if (! Directory.Exists(Path.Combine(baseDirectory, "lib" + Path.DirectorySeparatorChar + 
"chronojump"))) {
+                       baseDirectory = System.IO.Path.Combine(baseDirectory, "..");
+               }
+               return baseDirectory;
+       }
+
+       public static string GetDataDir(){
+               return System.IO.Path.Combine(GetPrefixDir(),
+                       "share" + Path.DirectorySeparatorChar + "chronojump");
+       }
+
+       public static string GetImagesDir(){
+               return System.IO.Path.Combine(GetDataDir(),"images");
+       }
+
+       public static string GetVideoTempFileName() {
+               return Path.Combine(
+                               Path.GetTempPath(), Constants.VideoTemp +
+                               GetMultimediaExtension(Constants.MultimediaItems.VIDEO));
+       }
+
+       public static bool CopyTempVideo(int sessionID, Constants.TestTypes type, int uniqueID) {
+               string origin = GetVideoTempFileName();
+               string destination = GetVideoFileName(sessionID, type, uniqueID);
+               Console.WriteLine("destination is: " + destination);
+               if(File.Exists(origin)) {
+                       CreateVideoSessionDirIfNeeded(sessionID);
+                       /*
+                        * no more move it, just copy it, because maybe is still being recorded
+                        try {
+                        File.Move(origin, destination);
+                        } catch {
+                        */
+                       File.Copy(origin, destination, true); //can be overwritten
+                       //}
+                       return true;
+               } else
+                       return false;
+       }
+
+       public static void DeleteVideo(int sessionID, Constants.TestTypes type, int uniqueID) {
+               string fileName = GetVideoFileName(sessionID, type, uniqueID);
+               if(File.Exists(fileName))
+                       File.Delete(fileName);
+       }
+        public static string GetMultimediaExtension (string filename)
+        {
+                if(UtilMultimedia.GetImageType(filename) == UtilMultimedia.ImageTypes.JPEG)
+                        return Constants.ExtensionPhoto; 
+                if(UtilMultimedia.GetImageType(filename) == UtilMultimedia.ImageTypes.PNG)
+                        return Constants.ExtensionPhotoPng; 
+
+                return "";
+        }
+
+        public static string GetMultimediaExtension (Constants.MultimediaItems multimediaItem) {
+                if(multimediaItem == Constants.MultimediaItems.VIDEO)
+                        return Constants.ExtensionVideo;
+                else if(multimediaItem == Constants.MultimediaItems.PHOTO)
+                        return Constants.ExtensionPhoto;
+                else //multimediaItem == Constants.MultimediaItems.PHOTOPNG
+                        return Constants.ExtensionPhotoPng;
+        }
+
+               public static string GetVideoFileName (int sessionID, Constants.TestTypes testType, int 
uniqueID) {
+                return GetVideoSessionDir(sessionID) + Path.DirectorySeparatorChar +
+                        testType.ToString() + "-" + uniqueID.ToString() +
+                        GetMultimediaExtension(Constants.MultimediaItems.VIDEO);
+        }
+
+               public static void CreateVideoSessionDirIfNeeded (int sessionID) {
+                string sessionDir = GetVideoSessionDir(sessionID);
+                if( ! Directory.Exists(sessionDir)) {
+                        Directory.CreateDirectory (sessionDir);
+                        Console.WriteLine ("created dir:", sessionDir);
+                }
+        }
+
+        public static string GetVideoSessionDir (int sessionID) {
+                return GetVideosDir() + Path.DirectorySeparatorChar + sessionID.ToString();
+        }   
+
+        public static string GetVideosDir() {
+                return Path.Combine(
+                                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+                                "Chronojump" + Path.DirectorySeparatorChar + "multimedia" +
+                                Path.DirectorySeparatorChar + "videos"); 
+        }      
+
+}
diff --git a/testing-stuff/ffmpegCapture/utilAll.cs b/testing-stuff/ffmpegCapture/utilAll.cs
new file mode 100644
index 00000000..1f106f83
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/utilAll.cs
@@ -0,0 +1,134 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2004-2017   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System;
+using System.Diagnostics;      //for detect OS
+using System.IO;               //for detect OS
+using System.Reflection; // Read Version
+
+//this class tries to be a space for methods that are used in different classes
+//in chronojump and chronojump_mini
+//we do not use util.cs in mini because it has lot of calls to other files
+public class UtilAll
+{
+       static bool printedOS = false;
+
+       //Eg. 1.6.2.0
+       public static string ReadVersion()
+       {
+               Version version = Assembly.GetExecutingAssembly().GetName().Version;
+               return version.ToString();
+       }       
+       
+
+       //Adapted from Mono. A developer's notebook. p 244
+       
+       //this is used in chronojump for working with the ports,
+       //in chronojump we compile now for Linux with Mono and for Windows with .NET
+       //it should be something like IsDotNet()
+       public static bool IsWindows() {
+               string os = GetOS();
+               if(os.ToUpper().StartsWith("WIN"))
+                       return true;
+               else 
+                       return false;
+       }
+       
+       public static string GetOS() {
+               OperatingSystem os = Environment.OSVersion;
+               string platform = os.Platform.ToString();
+
+               //detect a Mac that seems an Unix
+               if(platform == "Unix" && GetOSEnum() == OperatingSystems.MACOSX)
+                       platform = "Unix (MacOSX)";
+
+               string osString =  string.Format("{0}, {1}", platform, os.Version);
+
+               if(! printedOS) {
+                       Console.WriteLine("GetOS: " + osString);
+                       printedOS = true;
+               }
+               
+               return osString;
+       }
+
+       public enum OperatingSystems { WINDOWS, LINUX, MACOSX };
+
+       public static OperatingSystems GetOSEnum() 
+       {
+               
//http://stackoverflow.com/questions/10138040/how-to-detect-properly-windows-linux-mac-operating-systems
+               switch (Environment.OSVersion.Platform)
+               {
+                       case PlatformID.Unix:
+                               // Well, there are chances MacOSX is reported as Unix instead of MacOSX.
+                               // Instead of platform check, we'll do a feature checks (Mac specific root 
folders)
+                               if (Directory.Exists("/Applications")
+                                               & Directory.Exists("/System")
+                                               & Directory.Exists("/Users")
+                                               & Directory.Exists("/Volumes"))
+                                       return OperatingSystems.MACOSX;
+                               else
+                                       return OperatingSystems.LINUX;
+
+                       case PlatformID.MacOSX:
+                               return OperatingSystems.MACOSX;
+
+                       default:
+                               return OperatingSystems.WINDOWS;
+               }
+       }
+       
+       
+       public static string GetApplicationDataDir() {
+               return Path.Combine(
+                               Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+                               "Chronojump");
+       }
+       
+       public static string GetECapSimSignalFileName() {
+               return Path.Combine(GetApplicationDataDir() +  Path.DirectorySeparatorChar + 
"eCapSimSignal.txt");
+       }
+       
+       
+       
+       //if passed (number=1, digits=4)
+       //takes 1 and returns "0001" 
+       public static string DigitsCreate (int number, int digits)
+       {
+               string str = number.ToString();
+               while(str.Length < digits)
+                       str = "0" + str;
+               return str;
+       }
+
+       // ----------- logs -----------------------
+       
+
+       public static string GetTempDir() {
+               string path = Path.GetTempPath();
+
+               path = path.TrimEnd(Path.DirectorySeparatorChar);
+               //on Linux folder cannot be opened either with '/' at the end, or without it
+
+               return path;
+       }
+
+
+}
diff --git a/testing-stuff/ffmpegCapture/utilMultimedia.cs b/testing-stuff/ffmpegCapture/utilMultimedia.cs
new file mode 100644
index 00000000..0acb98b3
--- /dev/null
+++ b/testing-stuff/ffmpegCapture/utilMultimedia.cs
@@ -0,0 +1,100 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or   
+ *    (at your option) any later version.
+ *    
+ * ChronoJump is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *    GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Copyright (C) 2004-2017   Xavier de Blas <xaviblas gmail com> 
+ */
+
+using System;
+using System.Text; //StringBuilder
+using System.Collections; //ArrayList
+using System.Collections.Generic; //List
+using System.Diagnostics;      //for detect OS
+using System.IO;               //for detect OS
+//using Cairo;
+//using Gdk;
+
+//this class tries to be a space for methods that are used in different classes
+public class UtilMultimedia
+{
+       /*
+        * VIDEO
+        */
+
+       public static List<string> GetVideoDevices ()
+       {
+               /*
+                * TODO: reimplement this with ffmpeg
+                *
+               List<LongoMatch.Video.Utils.Device> devices = 
LongoMatch.Video.Utils.Device.ListVideoDevices();
+               string [] devicesStr = new String[devices.Count];
+               int count = 0;
+               LogB.Information("Searching video devices");
+               foreach(LongoMatch.Video.Utils.Device dev in devices) {
+                       devicesStr[count++] = dev.ID.ToString();
+                       LogB.Information(dev.ID.ToString());
+               }
+               return devicesStr;
+               */
+
+
+               //on Linux search for video0, video1, ...
+               if(UtilAll.GetOSEnum() == UtilAll.OperatingSystems.LINUX)
+                       return GetVideoDevicesLinux();
+               else if(UtilAll.GetOSEnum() == UtilAll.OperatingSystems.WINDOWS)
+                       return GetVideoDevicesWindows();
+               else
+                       return new List<string>();
+       }
+
+       public static List<string> GetVideoDevicesLinux ()
+       {
+               List<string> list = new List<string>();
+               string prefix = "/dev/";
+               var dir = new DirectoryInfo(prefix);
+               foreach(var file in dir.EnumerateFiles("video*"))
+                       /*
+                        * return 0, 1, ...
+                        if( file.Name.Length > 5 &&                            //there's something more than 
"video", like "video0" or "video1", ...
+                        char.IsNumber(file.Name, 5) )          //and it's a number
+                        list.Add(Convert.ToInt32(file.Name[5]));                       //0 or 1, or ...
+                        */
+                       //return "/dev/video0", "/dev/video1", ...
+                       list.Add(prefix + file.Name);
+
+               return list;
+       }
+
+       public static List<string> GetVideoDevicesWindows ()
+       {
+               return WebcamFfmpegGetDevicesWindows.GetDevices();
+       }
+
+       /*
+        * IMAGES
+        */
+
+       public enum ImageTypes { UNKNOWN, PNG, JPEG }
+       public static ImageTypes GetImageType(string filename)
+       {
+               if(filename.ToLower().EndsWith("jpeg") || filename.ToLower().EndsWith("jpg"))
+                       return ImageTypes.JPEG;
+               else if(filename.ToLower().EndsWith("png"))
+                       return ImageTypes.PNG;
+
+               return ImageTypes.UNKNOWN;
+       }
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]