diff --git a/ISCamRecorder/CvCamera.cs b/ISCamRecorder/CvCamera.cs index 754afad..1bb71fa 100644 --- a/ISCamRecorder/CvCamera.cs +++ b/ISCamRecorder/CvCamera.cs @@ -122,7 +122,7 @@ /// public void SaveToFile() { if (_RecFrames.Count < 1) return; - Debug.WriteLine($"{_CamID} starts saving with {CameraFPS:0.0}fps."); + Common.DebugOut($"{_CamID} starts saving with {CameraFPS:0.0}fps."); // 保存先確保 var outDir2 = Path.Combine(_MF.OutputDir, _CamID); Directory.CreateDirectory(outDir2); @@ -140,7 +140,7 @@ writer.Release(); _RecFrames.Clear(); - Debug.WriteLine($"{_CamID} ends saving."); + Common.DebugOut($"{_CamID} ends saving."); } /// diff --git a/ISCamRecorder/ISCamera.cs b/ISCamRecorder/ISCamera.cs index a154853..088e483 100644 --- a/ISCamRecorder/ISCamera.cs +++ b/ISCamRecorder/ISCamera.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; +using System.Threading; using System.IO; using System.Diagnostics; using TIS.Imaging; @@ -26,8 +26,11 @@ SinkListener _SinkListener = new SinkListener(); // Sinkリスナー IFrameQueueBuffer[] _bufferlist = null; // 録画バッファ bool _Recoding = false; // 録画中フラグ + + public ManualResetEvent Ready { get; private set; } // 録画準備完了シグナル + public float CameraFPS { get; private set; } = 0; // カメラFPS + public bool DeviceValid { get { return _Cam?.DeviceValid ?? false; } } // デバイス有効・無効 - public float CameraFPS { get; private set; } = 0; /// /// コンストラクタ @@ -41,6 +44,7 @@ _CamID = $"Cam{_SerialNumber.Substring(_SerialNumber.Length - 2)}"; _RecSink = new FrameQueueSink(_SinkListener, MediaSubtypes.RGB32); _PreviewSink = new FrameQueueSink(CaptureFrame, MediaSubtypes.RGB32, 5); + Ready = new ManualResetEvent(false); } /// @@ -61,14 +65,14 @@ try { if (File.Exists(ICCF_FILE)){ _Cam.LoadDeviceState(ICCFImport.Import(ICCF_FILE), false); - Debug.WriteLine($"{_CamID} loaded config {ICCF_FILE}"); + Common.DebugOut($"{_CamID} loaded config {ICCF_FILE}"); } else { - //Debug.WriteLine($"Can't find config {ICCF_FILE}"); + //Common.DebugOut($"Can't find config {ICCF_FILE}"); _Cam.VideoFormat = _Cam.VideoFormats.FirstOrDefault( c => c.Name.Equals(CAMERA_FORMAT)); _Cam.DeviceFrameRate = _Cam.DeviceFrameRates.FirstOrDefault( c => (c > FRAME_RATE - 0.1F && c < FRAME_RATE + 0.1F)); - Debug.WriteLine($"{_CamID} sets {_Cam.VideoFormat}, {_Cam.DeviceFrameRate:0.0}fps"); + Common.DebugOut($"{_CamID} sets {_Cam.VideoFormat}, {_Cam.DeviceFrameRate:0.0}fps"); } } catch (ICException iex) { MessageBox.Show(iex.Message, $"{_CamID} Error", @@ -137,20 +141,32 @@ /// public void RecordToMemory(float recodingLimit) { if (!_Cam.DeviceValid) return; - Debug.WriteLine($"{_CamID} starts recoding."); - _Recoding = true; - ClearBuffer(); + _Recoding = false; + // メモリ確保 + ClearBuffer(); var framesToCapture = (int)(recodingLimit * CameraFPS) + 1; _RecSink.AllocAndQueueBuffers(framesToCapture); + Ready.Set(); + Common.DebugOut($"{_CamID} ready for recoding."); + + // 撮影待機 + while (!_Recoding) { Thread.Sleep(0); } + // 撮影 + Common.DebugOut($"{_CamID} starts recoding."); while (_Recoding) { if (framesToCapture <= _RecSink.OutputQueueSize + 1) break; } // 画像バッファに変換 _bufferlist = _RecSink.PopAllOutputQueueBuffers(); _Recoding = false; - Debug.WriteLine($"{_CamID} ends recoding with {_bufferlist.Length} buffers."); + Common.DebugOut($"{_CamID} ends recoding with {_bufferlist.Length} frames."); + } + + // 録画開始 + public void StartRecoding() { + _Recoding = true; } /// @@ -159,7 +175,7 @@ /// public void SaveToFile() { if (!_Cam.DeviceValid) return; - Debug.WriteLine($"{_CamID} starts saving with {CameraFPS}fps."); + Common.DebugOut($"{_CamID} starts saving with {CameraFPS}fps."); // 保存先確保 var outDir2 = Path.Combine(_MF.OutputDir, _CamID); Directory.CreateDirectory(outDir2); @@ -196,7 +212,7 @@ // 終了処理 writer.End(); ClearBuffer(); - Debug.WriteLine($"{_CamID} ends saving."); + Common.DebugOut($"{_CamID} ends saving."); } /// diff --git a/ISCamRecorder/MainForm.cs b/ISCamRecorder/MainForm.cs index 13b5939..5b60566 100644 --- a/ISCamRecorder/MainForm.cs +++ b/ISCamRecorder/MainForm.cs @@ -5,6 +5,7 @@ using System.Drawing; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; @@ -237,7 +238,7 @@ _RecodingThread = Task.Run(RecodingThread); } else if (State == STATE.Recoding) { // 中断 - Debug.WriteLine("Stop recoding"); + Common.DebugOut("Stop recoding"); _Cameras.ForEach(c => c.StopRecoding()); } } @@ -247,8 +248,7 @@ /// private void RecodingThread() { - // 録画開始 - _Sounds[0].Play(); + // 録画準備 this.Invoke((MethodInvoker)delegate { for (var i = 0; i < _Cameras.Count; i++) { if (Setting.RecCameras[i]) _Cameras[i].ChangeSink(true); @@ -258,18 +258,30 @@ State = STATE.Recoding; this.UpdateControlState(); }); - _Sensor.StartRecoding(TxtSubjectName.Text); - // 録画 + // 録画スレッド開始 Task[] tasks = new Task[_Cameras.Count]; + List waits = new List(); for (var i = 0; i < _Cameras.Count; i++) { if (Setting.RecCameras[i]) { var cam = _Cameras[i]; + if (cam.DeviceValid) waits.Add(cam.Ready); tasks[i] = Task.Run(() => cam.RecordToMemory(Setting.RecodingLimit)); } else { tasks[i] = Task.Run(() => { }); } } + + // 録画準備待機 + ManualResetEvent.WaitAll(waits.ToArray()); + Common.DebugOut("全カメラ準備完了"); + + // 録画開始 + _Cameras.ForEach(c => c.StartRecoding()); + _Sensor.StartRecoding(TxtSubjectName.Text); + _Sounds[0].Play(); + + // 録画終了待機 Task.WaitAll(tasks); // 保存準備 @@ -304,7 +316,7 @@ this.UpdateControlState(); }); _Sounds[2].Play(); - Debug.WriteLine("_RecodingThread ends"); + Common.DebugOut("_RecodingThread ends"); } /// @@ -369,11 +381,11 @@ const int timeout = 2000; _SerialThread.Wait(timeout); - Debug.WriteLine("_SerialThread ends"); + Common.DebugOut("_SerialThread ends"); _CvCameraThread.Wait(timeout); - Debug.WriteLine("_CvCameraThread ends"); + Common.DebugOut("_CvCameraThread ends"); _TriggerThread.Wait(timeout); - Debug.WriteLine("_TriggerThread ends"); + Common.DebugOut("_TriggerThread ends"); this.Invoke((MethodInvoker)delegate { this.Close(); diff --git a/ISCamRecorder/Program.cs b/ISCamRecorder/Program.cs index d3e3f8e..aeb7900 100644 --- a/ISCamRecorder/Program.cs +++ b/ISCamRecorder/Program.cs @@ -4,8 +4,10 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using System.Diagnostics; namespace ISCamRecorder { + internal static class Program { /// /// アプリケーションのメイン エントリ ポイントです。 @@ -27,4 +29,14 @@ Application.Run(new MainForm()); } } + + // 共通クラス + public static class Common { + + public static void DebugOut(string msg) { + var now = DateTime.Now; + var timeStr = String.Format("{0:HH:mm:ss.fff}", now); + Debug.WriteLine($"[{timeStr}] {msg}"); + } + } } diff --git a/ISCamRecorder/SensorData.cs b/ISCamRecorder/SensorData.cs index 6a89d14..e1666b9 100644 --- a/ISCamRecorder/SensorData.cs +++ b/ISCamRecorder/SensorData.cs @@ -60,7 +60,7 @@ var portname = GetSerialPort(); if (portname.Length < 1) { #if DEBUG - Debug.WriteLine($"No Serial Connection."); + Common.DebugOut($"No Serial Connection."); #else MessageBox.Show("シリアルデバイスに接続できません", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); @@ -82,10 +82,10 @@ try { _Serial.Open(); } catch (Exception ex) { - Debug.WriteLine(ex.Message); + Common.DebugOut(ex.Message); return false; } - Debug.WriteLine($"Serial Connect {portname}."); + Common.DebugOut($"Serial Connect {portname}."); return true; } @@ -174,7 +174,7 @@ baseline[0] = (float)ValuesB.Average(); baseline[1] = (float)ValuesR.Average(); baseline[2] = (float)ValuesG.Average(); - //Debug.WriteLine($"逆血閾値 {_ReverseBloodThreshold} Baseline B,R,G={baseline[0]:0.0}, {baseline[1]:0.0}, {baseline[2]:0.0}"); + //Common.DebugOut($"逆血閾値 {_ReverseBloodThreshold} Baseline B,R,G={baseline[0]:0.0}, {baseline[1]:0.0}, {baseline[2]:0.0}"); } if (_IsRecoding) { @@ -187,7 +187,7 @@ count = detectData.Where(v => v >= _ReverseBloodThreshold).Count(); else count = detectData.Where(v => v <= _ReverseBloodThreshold).Count(); - //Debug.WriteLine($"逆血検出数 {count}"); + //Common.DebugOut($"逆血検出数 {count}"); if (!_IsReverseBlood && count >= _MF.Setting.RBDetectCount) { _IsReverseBlood = true; _MF.ReverseBlood();