diff --git a/ISCamRecorder/ISCamera.cs b/ISCamRecorder/ISCamera.cs index 1801e68..d38da35 100644 --- a/ISCamRecorder/ISCamera.cs +++ b/ISCamRecorder/ISCamera.cs @@ -14,14 +14,16 @@ readonly string CAMERA_FORMAT = "RGB32 (1920x1080)"; // 設定ファイル無い時の解像度 readonly float FRAME_RATE = 40F; // 設定ファイル無い時のFPS - ICImagingControl _Cam; // カメラオブジェクト + ICImagingControl _Cam; // カメラオブジェクト string _SerialNumber; // シリアル番号 + string _CamID; // カメラID VCDButtonProperty _Trigger; // トリガー設定 - FrameRateCounter _Fps = new FrameRateCounter(10); // フレームレート計測 + FrameRateCounter _Fps = new FrameRateCounter(10); // フレームレート計測 + FrameQueueSink _PreviewSink; // プレビューSink + FrameQueueSink _RecSink; // 録画Sink SinkListener _SinkListener = new SinkListener(); - FrameQueueSink _PreviewSink; - FrameQueueSink _RecSink; - IFrameQueueBuffer[] _bufferlist; + IFrameQueueBuffer[] _bufferlist = null; // 録画バッファ + bool _Recoding = false; // 録画中フラグ public float FrameRate { get { return _Fps.FrameRate; } } @@ -33,6 +35,9 @@ public ISCamera(ICImagingControl cameraControl, string serialNumber) { _Cam = cameraControl; _SerialNumber = serialNumber; + _CamID = $"Cam{_SerialNumber.Substring(_SerialNumber.Length - 2)}"; + _RecSink = new FrameQueueSink(_SinkListener, MediaSubtypes.RGB32); + _PreviewSink = new FrameQueueSink(CaptureFrame, MediaSubtypes.RGB32, 5); } /// @@ -51,17 +56,17 @@ try { if (File.Exists(ICCF_FILE)){ _Cam.LoadDeviceState(ICCFImport.Import(ICCF_FILE), false); - Debug.WriteLine($"Camera #{_SerialNumber} loaded config {ICCF_FILE}"); + Debug.WriteLine($"{_CamID} loaded config {ICCF_FILE}"); } else { //Debug.WriteLine($"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($"Camera #{_SerialNumber} sets {_Cam.VideoFormat}, {_Cam.DeviceFrameRate:0.0}fps"); + Debug.WriteLine($"{_CamID} sets {_Cam.VideoFormat}, {_Cam.DeviceFrameRate:0.0}fps"); } } catch (ICException iex) { - MessageBox.Show(iex.Message, "Camera Error", + MessageBox.Show(iex.Message, $"{_CamID} Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } @@ -69,11 +74,8 @@ // 表示設定 _Cam.LiveDisplayDefault = false; SetDisplaySize(); - _Cam.ImageRingBufferSize = 5; _Trigger = _Cam.VCDPropertyItems.Find( VCDGUIDs.VCDID_TriggerMode, VCDGUIDs.VCDElement_SoftwareTrigger); - _RecSink = new FrameQueueSink(_SinkListener, MediaSubtypes.RGB32); - _PreviewSink = new FrameQueueSink(CaptureFrame, MediaSubtypes.RGB32, 5); _Cam.Sink = _PreviewSink; _Cam.LiveStart(); @@ -95,39 +97,54 @@ /// /// 録画 /// - public void RecordToMemory() { - Debug.WriteLine($"Cam {_SerialNumber} starts recoding."); - var framesToCapture = 30; + public void RecordToMemory(int framesToCapture) { + Debug.WriteLine($"{_CamID} starts recoding."); + _Recoding = true; + ClearBuffer(); + // メモリ確保 _RecSink.AllocAndQueueBuffers(framesToCapture); - while (true) { + // 撮影 + while (_Recoding) { if (framesToCapture <= _RecSink.OutputQueueSize + 1) break; } + // 画像バッファに変換 _bufferlist = _RecSink.PopAllOutputQueueBuffers(); - Debug.WriteLine($"Cam {_SerialNumber} buffersize {_bufferlist.Length}."); + _Recoding = false; + Debug.WriteLine($"{_CamID} ends recoding with {_bufferlist.Length} buffers."); + } + /// + /// ファイル保存 + /// + /// + public void SaveToFile(string outDir) { + Debug.WriteLine($"{_CamID} starts saving."); + // 保存先確保 + var outDir2 = Path.Combine(outDir, _CamID); + Directory.CreateDirectory(outDir2); + // ファイル保存 for (int i = 0; i < _bufferlist.Length; i++) { - - //デバイスが生成したフレーム番号が格納されます。 - string strFrameNumber = _bufferlist[i].FrameMetadata.DeviceFrameNumber.ToString(); - - //(有効な場合)デバイスのタイムスタンプが格納されます。 - // デバイス固有のタイムソースによるタイムスタンプです。 - string strDeviceTimeStamp = _bufferlist[i].FrameMetadata.DeviceTimeStamp.ToString(); - //このフレームの最初のパケットをドライバが受信した時刻が格納されます。 string strSampleStartTime = _bufferlist[i].FrameMetadata.DriverFrameFirstPacketTime.ToString(@"hhmmss\.fff"); - //ドライバがこのフレームに与えたフレーム番号が格納されます。 - string strDriverFrameNumber = _bufferlist[i].FrameMetadata.DriverFrameNumber.ToString(); - - var fileName = $"Cam{_SerialNumber.Substring(_SerialNumber.Length-2)}_" + strSampleStartTime + ".jpg"; - TIS.Imaging.FrameExtensions.SaveAsJpeg(_bufferlist[i], fileName, 80); + var fileName = $"{_CamID}_{strSampleStartTime}.jpg"; + var filePath = Path.Combine(outDir2, fileName); + FrameExtensions.SaveAsJpeg(_bufferlist[i], filePath, 80); } + // バッファメモリ解放 + ClearBuffer(); + Debug.WriteLine($"{_CamID} ends saving."); + } - _bufferlist = null; - GC.Collect(); + private void ClearBuffer() { + if (_bufferlist != null) { + _bufferlist = null; + GC.Collect(); + } + } - Debug.WriteLine($"Cam {_SerialNumber} ends recoding."); + public void StopRecoding() { + _Recoding = false; } /// diff --git a/ISCamRecorder/MainForm.Designer.cs b/ISCamRecorder/MainForm.Designer.cs index 93ebbd1..c39de7b 100644 --- a/ISCamRecorder/MainForm.Designer.cs +++ b/ISCamRecorder/MainForm.Designer.cs @@ -43,7 +43,7 @@ this.label2 = new System.Windows.Forms.Label(); this.LblAvailableMemory = new System.Windows.Forms.Label(); this.LblRecodingMemory = new System.Windows.Forms.Label(); - this.textBox1 = new System.Windows.Forms.TextBox(); + this.TxtOutputDir = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.BtnRecodeMovie = new System.Windows.Forms.Button(); this.TxtTriggerFPS = new System.Windows.Forms.TextBox(); @@ -323,13 +323,13 @@ this.LblRecodingMemory.TabIndex = 12; this.LblRecodingMemory.Text = "消費する物理メモリ"; // - // textBox1 + // TxtOutputDir // - this.textBox1.Location = new System.Drawing.Point(523, 27); - this.textBox1.Name = "textBox1"; - this.textBox1.Size = new System.Drawing.Size(235, 19); - this.textBox1.TabIndex = 13; - this.textBox1.Text = "D:\\usr\\DL"; + this.TxtOutputDir.Location = new System.Drawing.Point(523, 27); + this.TxtOutputDir.Name = "TxtOutputDir"; + this.TxtOutputDir.Size = new System.Drawing.Size(235, 19); + this.TxtOutputDir.TabIndex = 13; + this.TxtOutputDir.Text = "D:\\usr\\DL"; // // label3 // @@ -377,7 +377,7 @@ this.Controls.Add(this.TxtTriggerFPS); this.Controls.Add(this.BtnRecodeMovie); this.Controls.Add(this.label3); - this.Controls.Add(this.textBox1); + this.Controls.Add(this.TxtOutputDir); this.Controls.Add(this.LblRecodingMemory); this.Controls.Add(this.LblAvailableMemory); this.Controls.Add(this.label2); @@ -443,7 +443,7 @@ private System.Windows.Forms.Label label2; private System.Windows.Forms.Label LblAvailableMemory; private System.Windows.Forms.Label LblRecodingMemory; - private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox TxtOutputDir; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button BtnRecodeMovie; private System.Windows.Forms.TextBox TxtTriggerFPS; diff --git a/ISCamRecorder/MainForm.cs b/ISCamRecorder/MainForm.cs index 6577f63..b5e0051 100644 --- a/ISCamRecorder/MainForm.cs +++ b/ISCamRecorder/MainForm.cs @@ -9,6 +9,7 @@ using System.Windows.Forms; using System.Diagnostics; using System.Reflection; +using System.IO; namespace ISCamRecorder { public partial class MainForm : Form { @@ -170,7 +171,7 @@ /// private void TxtRecodingDulation_KeyPress(object sender, KeyPressEventArgs e) { //バックスペースが押された時は有効(Deleteキーも有効) - if (e.KeyChar == '\b') { + if (e.KeyChar == '\b' || e.KeyChar == '.') { return; } @@ -186,16 +187,38 @@ /// /// private void BtnRecodeMovie_Click(object sender, EventArgs e) { - // 録画モードへ変更 - _Cameras.ForEach(c => c.ChangeSink(true)); - // 録画 - Task[] tasks = new Task[4]; - for (var i = 0; i < tasks.Length; i++) { - tasks[i] = Task.Run(_Cameras[i].RecordToMemory); + if (BtnRecodeMovie.Text.Equals("中断")) { + _Cameras.ForEach(c => c.StopRecoding()); + } else { + BtnRecodeMovie.Text = "撮影中"; + // 録画モードへ変更 + _Cameras.ForEach(c => c.ChangeSink(true)); + // 録画条件設定 + var frameRate = _Cameras.Select(c => c.FrameRate).Average(); + var framesToCapture = (int)(float.Parse(TxtRecodingDulation.Text) + * frameRate + 1.0F); + var outputDir = Path.Combine(TxtOutputDir.Text, + "rec" + DateTime.Now.ToString("yyyyMMdd_HHmmss")); + Directory.CreateDirectory(outputDir); + // 録画 + Task[] tasks = new Task[4]; + for (var i = 0; i < _Cameras.Count; i++) { + var cam = _Cameras[i]; + tasks[i] = Task.Run(() => cam.RecordToMemory(framesToCapture)); + } + Task.WaitAll(tasks); + // 保存 + BtnRecodeMovie.Text = "保存中"; + for (var i = 0; i < _Cameras.Count; i++) { + var cam = _Cameras[i]; + tasks[i] = Task.Run(() => cam.SaveToFile(outputDir)); + } + Task.WaitAll(tasks); + + // プレビューモードへ変更 + _Cameras.ForEach(c => c.ChangeSink(false)); + BtnRecodeMovie.Text = "動画撮影"; } - Task.WaitAll(tasks); - // プレビューモードへ変更 - _Cameras.ForEach(c => c.ChangeSink(false)); } } }