Commit 5c7c4488 authored by Xavier de Blas's avatar Xavier de Blas

person photo preview and capture with ffmpeg done (at least on Linux)

parent 83a89b21
......@@ -335,33 +335,12 @@
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">4</property>
<property name="spacing">6</property>
<child>
<widget class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">8</property>
<child>
<widget class="GtkButton" id="button_add_photo_file">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Add photo from file</property>
<signal name="clicked" handler="on_button_add_photo_file_clicked" swapped="no"/>
<child>
<widget class="GtkImage" id="image_photo_from_file">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox_camera">
<property name="visible">True</property>
......@@ -375,10 +354,34 @@
<property name="tooltip" translatable="yes">Start webcam</property>
<signal name="clicked" handler="on_button_take_photo_start_end_camera_clicked" swapped="no"/>
<child>
<widget class="GtkImage" id="image_photo_start_end_camera">
<widget class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="spacing">4</property>
<child>
<widget class="GtkImage" id="image_photo_start_end_camera">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Preview</property>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
......@@ -406,15 +409,15 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</widget>
......@@ -425,6 +428,52 @@
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<widget class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Change</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button_add_photo_file">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip" translatable="yes">Add photo from file</property>
<signal name="clicked" handler="on_button_add_photo_file_clicked" swapped="no"/>
<child>
<widget class="GtkImage" id="image_photo_from_file">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
......@@ -607,9 +656,6 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkLabel" id="label218">
<property name="visible">True</property>
......@@ -2030,6 +2076,9 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
</child>
</widget>
......
......@@ -1074,73 +1074,33 @@ public class PersonAddModifyWindow
{
webcam.ExitCamera();
image_photo_start_end_camera.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "image_photo_start_camera.png");
button_take_photo_do.Sensitive = false;
button_take_photo_start_end_camera.TooltipText = Catalog.GetString("Start webcam");
return;
}
// B) start if it's not running
webcam = new WebcamMplayer (videoDevice);
Webcam.Result result = webcam.CapturePrepare (Webcam.CaptureTypes.PHOTO);
//webcam = new WebcamMplayer (videoDevice);
//Webcam.Result result = webcam.CapturePrepare (Webcam.CaptureTypes.PHOTO);
//constructor for playpreview
webcam = new WebcamFfmpeg (Webcam.Action.PLAYPREVIEW, UtilAll.GetOSEnum(), videoDevice);
Webcam.Result result = webcam.PlayPreviewNoBackground ();
if (! result.success)
{
LogB.Debug ("Webcam Mplayer error: ", result.error);
LogB.Debug ("Webcam Ffmpeg error: ", result.error);
new DialogMessage (Constants.MessageTypes.WARNING, result.error);
return;
}
image_photo_start_end_camera.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "image_photo_end_camera.png");
button_take_photo_do.Sensitive = true;
button_take_photo_start_end_camera.TooltipText = Catalog.GetString("Stop webcam");
/*
* TODO: reimplement this with ffmpeg
*
List<LongoMatch.Video.Utils.Device> devices = LongoMatch.Video.Utils.Device.ListVideoDevices();
if(devices.Count == 0) {
new DialogMessage(Constants.MessageTypes.WARNING, Constants.CameraNotFound);
return;
}
//deactivate camera to allow camera on edit person. videoOn will have same value to light checkbutton again later
app1_checkbutton_video.Active = false;
capturer = new CapturerBin();
CapturePropertiesStruct s = new CapturePropertiesStruct();
s.DeviceID = devices[0].ID;
s.CaptureSourceType = CaptureSourceType.System;
capturer.CaptureProperties = s;
capturer.Type = CapturerType.Snapshot;
capturer.Visible=true;
capturer.NewSnapshot += on_snapshot_done;
capturer.NewSnapshotMini += on_snapshot_mini_done;
capturerWindow = new Gtk.Window("Capturer");
capturerWindow.Add(capturer);
capturerWindow.Modal=true;
capturerWindow.SetDefaultSize(400,400);
person_win.Hide();
capturerWindow.ShowAll();
capturerWindow.Present();
capturerWindow.DeleteEvent += delegate(object sender, DeleteEventArgs e) {capturer.Close(); capturer.Dispose(); person_win.Show(); };
capturer.Run();
*/
}
void on_button_take_photo_do_clicked (object o, EventArgs args)
{
if(webcam == null)
return;
webcam = new WebcamFfmpeg (Webcam.Action.PLAYPREVIEW, UtilAll.GetOSEnum(), videoDevice);
if(webcam.Snapshot())
{
File.Copy(Util.GetMplayerPhotoTempFileNamePost(Util.ChangeChars(videoDevice, "/", "_")),
File.Copy(Util.GetWebcamPhotoTempFileNamePost(Util.ChangeChars(videoDevice, "/", "_")),
Util.GetPhotoPngFileName(false, currentPerson.UniqueID), true); //overwrite
string filenameMini = Util.GetPhotoPngFileName(true, currentPerson.UniqueID);
......@@ -1152,7 +1112,6 @@ public class PersonAddModifyWindow
}
image_photo_start_end_camera.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "image_photo_start_camera.png");
button_take_photo_do.Sensitive = false;
}
//libCesarplayer method, jpeg
......@@ -1271,7 +1230,6 @@ public class PersonAddModifyWindow
PersonAddModifyWindowBox.pDN = pDN;
PersonAddModifyWindowBox.app1_checkbutton_video = app1_checkbutton_video;
PersonAddModifyWindowBox.button_take_photo_do.Sensitive = false;
PersonAddModifyWindowBox.videoDevice = videoDevice;
PersonAddModifyWindowBox.person_win.Show ();
......
......@@ -1081,7 +1081,7 @@ public class Util
*/
//Pre: filename without 0001.png
public static string GetMplayerPhotoTempFileNamePre(string videoDevice)
public static string GetWebcamPhotoTempFileNamePre(string videoDevice)
{
string fileName = Constants.PhotoTemp;
......@@ -1089,9 +1089,9 @@ public class Util
}
//Pre: filename with 0001.png
public static string GetMplayerPhotoTempFileNamePost(string videoDevice)
public static string GetWebcamPhotoTempFileNamePost(string videoDevice)
{
return GetMplayerPhotoTempFileNamePre(videoDevice) + "0001.png";
return GetWebcamPhotoTempFileNamePre(videoDevice) + "0001.png";
}
......
/*
15 Feb 2019
//play 2 seconds of video and autoexit. works:
//ffplay JUMP_RJ-252.mp4 -autoexit -t 2
//but on webcam show it does not exit
//ffplay /dev/video0 -autoexit -t 2
//one solution will be to open camera with ffplay, close it pressing any button (keyboard or mouse):
//ffplay /dev/video0 -exitonkeydown -exitonmousedown
//and then press make photo that will be:
//webcam make picture on second two
//ffmpeg -f video4linux2 -s 640x480 -i /dev/video0 -ss 0:0:2 -frames 1 /tmp/out.jpg
17 setembre 2018
ffmpeg builds on windows only work on Windows 7 and above
......@@ -126,6 +140,7 @@ public abstract class Webcam
public abstract Result CapturePrepare (CaptureTypes captureType);
public abstract Result PlayPreview();
public abstract Result PlayPreviewNoBackground();
public abstract Result PlayFile(string filename);
......
......@@ -72,16 +72,43 @@ public class WebcamFfmpeg : Webcam
List<string> parameters = createParametersPlayPreview();
process = new Process();
bool success = ExecuteProcess.RunAtBackground (ref process, executable, parameters, true, false, false, false, false);
bool success = ExecuteProcess.RunAtBackground (ref process, executable, parameters, true, false, true, false, false);
if(! success)
{
process = null;
return new Result (false, "", programFfmpegNotInstalled);
}
streamWriter = process.StandardInput;
Running = true;
return new Result (true, "");
}
public override Result PlayPreviewNoBackground () //experimental
{
List<string> parameters = createParametersPlayPreview();
process = new Process();
ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, parameters, false, false);
if(! execute_result.success)
{
return new Result (false, "", programFfmpegNotInstalled);
}
return new Result (true, "");
}
//snapshot in 2 seconds
public override bool Snapshot ()
{
executable = "ffmpeg";
List<string> parameters = createParametersSnapshot();
process = new Process();
ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, parameters, false, false);
return execute_result.success;
}
public override Result PlayFile (string filename)
{
......@@ -102,12 +129,6 @@ public class WebcamFfmpeg : Webcam
return new Result (true, "");
}
public override bool Snapshot()
{
//only implemented on mplayer
return true;
}
public override Result VideoCaptureStart()
{
process = new Process();
......@@ -147,8 +168,42 @@ public class WebcamFfmpeg : Webcam
else
parameters.Insert (i ++, "video=" + videoDevice);
parameters.Insert (i++, "-exitonkeydown");
parameters.Insert (i++, "-exitonmousedown");
parameters.Insert (i++, "-window_title");
parameters.Insert (i++, "Chronojump webcam preview");
parameters.Insert (i++, "Preview. Press any key to exit.");
return parameters;
}
//ffmpeg -f v4l2 -s 400x400 -i /dev/video0 -ss 0:0:2 -frames 1 /tmp/out.jpg
private List<string> createParametersSnapshot()
{
// ffplay /dev/video0
List<string> parameters = new List<string>();
int i=0;
parameters.Insert (i ++, "-f");
if(os == UtilAll.OperatingSystems.LINUX)
parameters.Insert (i ++, "v4l2");
else //windows
parameters.Insert (i ++, "dshow");
parameters.Insert (i ++, "-s");
parameters.Insert (i ++, "400x400");
parameters.Insert (i ++, "-i");
if(os == UtilAll.OperatingSystems.LINUX)
parameters.Insert (i ++, videoDevice);
else
parameters.Insert (i ++, "video=" + videoDevice);
parameters.Insert (i ++, "-ss");
parameters.Insert (i ++, "0:0:2");
parameters.Insert (i ++, "-frames");
parameters.Insert (i ++, "1");
parameters.Insert (i ++, Util.GetWebcamPhotoTempFileNamePost(videoDeviceToFilename()));
parameters.Insert (i ++, "-y"); //overwrite
return parameters;
}
......@@ -272,7 +327,7 @@ public class WebcamFfmpeg : Webcam
LogB.Information("streamWriter is null: " + (streamWriter == null).ToString());
try {
streamWriter.Write('q');
//streamWriter.Flush(); //seems is not needed
streamWriter.Flush(); //seems is not needed
} catch {
//maybe capturer process (could be a window) has been closed by user
process = null;
......@@ -289,10 +344,16 @@ public class WebcamFfmpeg : Webcam
* without using this file copied from /tmp maybe is not finished, so a bad ended file is copied to .local/share/Chronojump/multimedia/video
*/
bool exitBucle = false;
do {
LogB.Information("waiting 100 ms to tmp capture file being unlocked");
System.Threading.Thread.Sleep(100);
} while( ExecuteProcess.IsFileLocked(new System.IO.FileInfo(Util.GetVideoTempFileName())) );
if (! File.Exists(Util.GetVideoTempFileName())) //PlayPreview does not have tmp file
exitBucle = true;
else if( ! ExecuteProcess.IsFileLocked(new System.IO.FileInfo(Util.GetVideoTempFileName())) ) //we are capturing, wait file is not locked
exitBucle = true;
} while(! exitBucle);
do {
LogB.Information("waiting 100 ms to end Ffmpeg");
......
......@@ -45,7 +45,7 @@ public class WebcamMplayer : Webcam
if(process != null)
return new Result (false, "");
string tempFile = Util.GetMplayerPhotoTempFileNamePost(videoDeviceToFilename());
string tempFile = Util.GetWebcamPhotoTempFileNamePost(videoDeviceToFilename());
Util.FileDelete(tempFile);
List<string> parameters = new List<string>();
......@@ -68,7 +68,7 @@ public class WebcamMplayer : Webcam
parameters.Insert (i ++, "driver=v4l2:gain=1:width=400:height=400:device=" + videoDevice + ":fps=10:outfmt=rgb16");
parameters.Insert (i ++, "tv://");
parameters.Insert (i ++, "-vf");
parameters.Insert (i ++, "screenshot=" + Util.GetMplayerPhotoTempFileNamePre(videoDeviceToFilename()));
parameters.Insert (i ++, "screenshot=" + Util.GetWebcamPhotoTempFileNamePre(videoDeviceToFilename()));
process = new Process();
bool success = ExecuteProcess.RunAtBackground (ref process, executable, parameters, true, false, true, true, true); //redirectInput, redirectOutput, redirectError
......@@ -105,6 +105,11 @@ public class WebcamMplayer : Webcam
//not implemented
return new Result (false, "");
}
public override Result PlayPreviewNoBackground () //experimental
{
//not implemented
return new Result (false, "");
}
public override Result PlayFile (string filename)
{
......@@ -263,7 +268,7 @@ public class WebcamMplayer : Webcam
private bool findIfThereAreImagesToConvert()
{
return (File.Exists(Util.GetMplayerPhotoTempFileNamePre(videoDeviceToFilename()) + "0001.png"));
return (File.Exists(Util.GetWebcamPhotoTempFileNamePre(videoDeviceToFilename()) + "0001.png"));
}
private bool convertImagesToVideo()
......@@ -275,7 +280,7 @@ public class WebcamMplayer : Webcam
parameters.Insert (1, "20");
parameters.Insert (2, "-y"); //force overwrite without asking
parameters.Insert (3, "-i"); //input files
parameters.Insert (4, Util.GetMplayerPhotoTempFileNamePre(videoDeviceToFilename()) + "%04d.png");
parameters.Insert (4, Util.GetWebcamPhotoTempFileNamePre(videoDeviceToFilename()) + "%04d.png");
parameters.Insert (5, Util.GetVideoTempFileName());
ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, parameters, true, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment