[chronojump] person photo preview and capture with ffmpeg done (at least on Linux)
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] person photo preview and capture with ffmpeg done (at least on Linux)
- Date: Fri, 15 Feb 2019 17:34:44 +0000 (UTC)
commit 5c7c44880c89d193c21ce782d9115dcb2e3546c4
Author: Xavier de Blas <xaviblas gmail com>
Date: Fri Feb 15 18:33:48 2019 +0100
person photo preview and capture with ffmpeg done (at least on Linux)
glade/person_win.glade | 111 +++++++++++++++++++++++++++++++++++--------------
src/gui/person.cs | 60 ++++----------------------
src/util.cs | 6 +--
src/webcam.cs | 15 +++++++
src/webcamFfmpeg.cs | 81 +++++++++++++++++++++++++++++++-----
src/webcamMplayer.cs | 13 ++++--
6 files changed, 187 insertions(+), 99 deletions(-)
---
diff --git a/glade/person_win.glade b/glade/person_win.glade
index 588d4323..6b173431 100644
--- a/glade/person_win.glade
+++ b/glade/person_win.glade
@@ -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>
diff --git a/src/gui/person.cs b/src/gui/person.cs
index 321b59b2..ca013d96 100644
--- a/src/gui/person.cs
+++ b/src/gui/person.cs
@@ -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 ();
diff --git a/src/util.cs b/src/util.cs
index faa6036a..bb839962 100644
--- a/src/util.cs
+++ b/src/util.cs
@@ -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";
}
diff --git a/src/webcam.cs b/src/webcam.cs
index 94592aa7..c51ff555 100644
--- a/src/webcam.cs
+++ b/src/webcam.cs
@@ -1,5 +1,19 @@
/*
+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);
diff --git a/src/webcamFfmpeg.cs b/src/webcamFfmpeg.cs
index 8f1a804f..e2f9a069 100644
--- a/src/webcamFfmpeg.cs
+++ b/src/webcamFfmpeg.cs
@@ -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");
diff --git a/src/webcamMplayer.cs b/src/webcamMplayer.cs
index b63512a4..155fee87 100644
--- a/src/webcamMplayer.cs
+++ b/src/webcamMplayer.cs
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]