From 77cb7c1142426ac99ddfb73be765645bf073df8c Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Fri, 23 Oct 2020 10:27:23 -0400 Subject: [PATCH 1/6] remove zero-length file during disposal --- .../Handlers/CircularBufferCaptureHandler.cs | 6 ---- .../Handlers/FileStreamCaptureHandler.cs | 28 ++++++++++++++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 43ffa50a..2758ef06 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -154,12 +154,6 @@ public void StopRecording() _receivedIFrame = false; } - /// - public override void Dispose() - { - this.CurrentStream?.Dispose(); - } - /// public override string TotalProcessed() { diff --git a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs index c0b1497b..d6ce90ff 100644 --- a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs @@ -36,7 +36,7 @@ public class FileStreamCaptureHandler : StreamCaptureHandler, IFileS public string Extension { get; set; } /// - /// The name of the current file associated with the FileStream. + /// The name of the file associated with the FileStream (without a path or extension). /// public string CurrentFilename { get; set; } @@ -63,9 +63,9 @@ public FileStreamCaptureHandler(string directory, string extension) MMALLog.Logger.LogDebug($"{nameof(FileStreamCaptureHandler)} created for directory {this.Directory} and extension {this.Extension}"); System.IO.Directory.CreateDirectory(this.Directory); - + var now = DateTime.Now.ToString("dd-MMM-yy HH-mm-ss"); - + int i = 1; var fileName = $"{this.Directory}/{now}.{this.Extension}"; @@ -94,12 +94,12 @@ public FileStreamCaptureHandler(string fullPath) this.CurrentFilename = Path.GetFileNameWithoutExtension(fileInfo.Name); var ext = fullPath.Split('.').LastOrDefault(); - + if (string.IsNullOrEmpty(ext)) { throw new ArgumentNullException(nameof(ext), "Could not get file extension from path string."); } - + this.Extension = ext; MMALLog.Logger.LogDebug($"{nameof(FileStreamCaptureHandler)} created for directory {this.Directory} and extension {this.Extension}"); @@ -112,14 +112,14 @@ public FileStreamCaptureHandler(string fullPath) } /// - /// Gets the filename that a FileStream points to. + /// Gets the filename that a FileStream points to without a path or extension. /// /// The filename. public string GetFilename() => (this.CurrentStream != null) ? Path.GetFileNameWithoutExtension(this.CurrentStream.Name) : string.Empty; /// - /// Gets the filepath that a FileStream points to. + /// Gets the full file pathname that a FileStream points to. /// /// The filepath. public string GetFilepath() => @@ -180,5 +180,19 @@ public override string TotalProcessed() { return $"{this.Processed}"; } + + /// + public override void Dispose() + { + base.Dispose(); + + // Disposing the stream leaves a zero-length file on disk. + try + { + File.Delete(this.CurrentStream.Name); + } + catch { } + } + } } From c91e732bfbcf964795c41911db97860aa665ace5 Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Fri, 23 Oct 2020 10:35:16 -0400 Subject: [PATCH 2/6] cleanup in circular buffer otherwise video handler deletes valid file --- .../Handlers/CircularBufferCaptureHandler.cs | 14 ++++++++++++++ .../Handlers/FileStreamCaptureHandler.cs | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 2758ef06..36b3844c 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -4,6 +4,7 @@ // using System; +using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -159,5 +160,18 @@ public override string TotalProcessed() { return $"{this.Processed}"; } + + /// + public override void Dispose() + { + base.Dispose(); + + // Disposing the stream leaves a zero-length file on disk. + try + { + File.Delete(this.CurrentStream.Name); + } + catch { } + } } } diff --git a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs index d6ce90ff..03388752 100644 --- a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs @@ -180,19 +180,5 @@ public override string TotalProcessed() { return $"{this.Processed}"; } - - /// - public override void Dispose() - { - base.Dispose(); - - // Disposing the stream leaves a zero-length file on disk. - try - { - File.Delete(this.CurrentStream.Name); - } - catch { } - } - } } From af99c90088a2cef6617313120356d9b66bd045fe Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Fri, 23 Oct 2020 10:47:18 -0400 Subject: [PATCH 3/6] edge case, dispose while recording --- .../Handlers/CircularBufferCaptureHandler.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 36b3844c..4b1e891d 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -5,6 +5,7 @@ using System; using System.IO; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -164,14 +165,21 @@ public override string TotalProcessed() /// public override void Dispose() { + // Check before the underlying stream handler disposes the stream. + var wasBuffering = this.CurrentStream == null && !_recordToFileStream; + base.Dispose(); - // Disposing the stream leaves a zero-length file on disk. - try + // Disposing the stream leaves a zero-length file on disk if the + // handler was not actively recording video and the buffer was valid. + if(wasBuffering) { - File.Delete(this.CurrentStream.Name); + try + { + File.Delete(this.CurrentStream.Name); + } + catch { } } - catch { } } } } From 8902fba42584f2965f4679e71bdcf3ffb0fa0313 Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Fri, 23 Oct 2020 10:58:50 -0400 Subject: [PATCH 4/6] move dispose to original location (reduce diff noise!) --- .../Handlers/CircularBufferCaptureHandler.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 4b1e891d..09278570 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -5,7 +5,6 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -156,12 +155,6 @@ public void StopRecording() _receivedIFrame = false; } - /// - public override string TotalProcessed() - { - return $"{this.Processed}"; - } - /// public override void Dispose() { @@ -172,7 +165,7 @@ public override void Dispose() // Disposing the stream leaves a zero-length file on disk if the // handler was not actively recording video and the buffer was valid. - if(wasBuffering) + if (wasBuffering) { try { @@ -181,5 +174,11 @@ public override void Dispose() catch { } } } + + /// + public override string TotalProcessed() + { + return $"{this.Processed}"; + } } } From ab1035a4b8462ed5b62708d52f9a86bdaabbae03 Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Fri, 23 Oct 2020 17:37:58 -0400 Subject: [PATCH 5/6] add an explicit zero-length file flag --- .../Handlers/CircularBufferCaptureHandler.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 09278570..d3ac30d1 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -21,6 +21,7 @@ public sealed class CircularBufferCaptureHandler : VideoStreamCaptureHandler private bool _recordToFileStream; private int _bufferSize; private bool _receivedIFrame; + private bool _fileIsEmpty; /// /// The circular buffer object responsible for storing image data. @@ -36,6 +37,9 @@ public CircularBufferCaptureHandler(int bufferSize) { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); + + // Prevent Dispose from trying to delete a non-existent file + _fileIsEmpty = true; } /// @@ -49,6 +53,7 @@ public CircularBufferCaptureHandler(int bufferSize, string directory, string ext { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); + _fileIsEmpty = true; } /// @@ -61,6 +66,7 @@ public CircularBufferCaptureHandler(int bufferSize, string fullPath) { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); + _fileIsEmpty = true; } /// @@ -86,6 +92,7 @@ public override void Process(ImageContext context) if (this.CurrentStream != null && this.CurrentStream.CanWrite) { this.CurrentStream.Write(this.Buffer.ToArray(), 0, this.Buffer.Size); + _fileIsEmpty = false; } this.Processed += this.Buffer.Size; @@ -95,6 +102,7 @@ public override void Process(ImageContext context) if (this.CurrentStream != null && this.CurrentStream.CanWrite) { this.CurrentStream.Write(context.Data, 0, context.Data.Length); + _fileIsEmpty = false; } this.Processed += context.Data.Length; @@ -156,16 +164,21 @@ public void StopRecording() } /// - public override void Dispose() + public override void Split() { - // Check before the underlying stream handler disposes the stream. - var wasBuffering = this.CurrentStream == null && !_recordToFileStream; + base.Split(); + _fileIsEmpty = true; + } + /// + public override void Dispose() + { base.Dispose(); - // Disposing the stream leaves a zero-length file on disk if the - // handler was not actively recording video and the buffer was valid. - if (wasBuffering) + // Disposing the stream can leave a zero-length file on disk if nothing + // was recorded into it -- but after recording has taken place, only + // calling Split will create a new empty file. + if (_fileIsEmpty) { try { From 02795973d336987af58e75933712a560ab54d2a9 Mon Sep 17 00:00:00 2001 From: Jon McGuire Date: Sun, 25 Oct 2020 09:14:31 -0400 Subject: [PATCH 6/6] moved FileIsEmpty flag to file stream base class --- .../Handlers/CircularBufferCaptureHandler.cs | 35 +---------------- .../Handlers/FileStreamCaptureHandler.cs | 38 +++++++++++++++++++ .../Handlers/VideoStreamCaptureHandler.cs | 5 ++- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index d3ac30d1..574ae376 100644 --- a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs @@ -21,7 +21,6 @@ public sealed class CircularBufferCaptureHandler : VideoStreamCaptureHandler private bool _recordToFileStream; private int _bufferSize; private bool _receivedIFrame; - private bool _fileIsEmpty; /// /// The circular buffer object responsible for storing image data. @@ -37,9 +36,6 @@ public CircularBufferCaptureHandler(int bufferSize) { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); - - // Prevent Dispose from trying to delete a non-existent file - _fileIsEmpty = true; } /// @@ -53,7 +49,6 @@ public CircularBufferCaptureHandler(int bufferSize, string directory, string ext { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); - _fileIsEmpty = true; } /// @@ -66,7 +61,6 @@ public CircularBufferCaptureHandler(int bufferSize, string fullPath) { _bufferSize = bufferSize; this.Buffer = new CircularBuffer(bufferSize); - _fileIsEmpty = true; } /// @@ -92,7 +86,7 @@ public override void Process(ImageContext context) if (this.CurrentStream != null && this.CurrentStream.CanWrite) { this.CurrentStream.Write(this.Buffer.ToArray(), 0, this.Buffer.Size); - _fileIsEmpty = false; + this.FileIsEmpty = false; } this.Processed += this.Buffer.Size; @@ -102,7 +96,7 @@ public override void Process(ImageContext context) if (this.CurrentStream != null && this.CurrentStream.CanWrite) { this.CurrentStream.Write(context.Data, 0, context.Data.Length); - _fileIsEmpty = false; + this.FileIsEmpty = false; } this.Processed += context.Data.Length; @@ -163,31 +157,6 @@ public void StopRecording() _receivedIFrame = false; } - /// - public override void Split() - { - base.Split(); - _fileIsEmpty = true; - } - - /// - public override void Dispose() - { - base.Dispose(); - - // Disposing the stream can leave a zero-length file on disk if nothing - // was recorded into it -- but after recording has taken place, only - // calling Split will create a new empty file. - if (_fileIsEmpty) - { - try - { - File.Delete(this.CurrentStream.Name); - } - catch { } - } - } - /// public override string TotalProcessed() { diff --git a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs index 03388752..313686a8 100644 --- a/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/FileStreamCaptureHandler.cs @@ -4,6 +4,7 @@ // using Microsoft.Extensions.Logging; +using MMALSharp.Common; using MMALSharp.Common.Utility; using System; using System.Collections.Generic; @@ -40,6 +41,12 @@ public class FileStreamCaptureHandler : StreamCaptureHandler, IFileS /// public string CurrentFilename { get; set; } + /// + /// When true, the Dispose method will delete the zero-length file identified by CurrentStream.Name. + /// Inheriting classes should set this to false any time they write to the file stream. + /// + protected bool FileIsEmpty { get; set; } + /// /// Creates a new instance of the class without provisions for writing to a file. Supports /// subclasses in which file output is optional. @@ -47,6 +54,9 @@ public class FileStreamCaptureHandler : StreamCaptureHandler, IFileS public FileStreamCaptureHandler() { MMALLog.Logger.LogDebug($"{nameof(FileStreamCaptureHandler)} empty ctor invoked, no file will be written"); + + // Prevent Dispose from attempting to delete a non-existent file. + this.FileIsEmpty = false; } /// @@ -80,6 +90,7 @@ public FileStreamCaptureHandler(string directory, string extension) this.CurrentFilename = Path.GetFileNameWithoutExtension(fileInfo.Name); this.CurrentStream = File.Create(fileName); + this.FileIsEmpty = true; } /// @@ -109,6 +120,14 @@ public FileStreamCaptureHandler(string fullPath) System.IO.Directory.CreateDirectory(this.Directory); this.CurrentStream = File.Create(fullPath); + this.FileIsEmpty = true; + } + + /// + public override void Process(ImageContext context) + { + base.Process(context); + this.FileIsEmpty = false; } /// @@ -161,6 +180,7 @@ public virtual void NewFile() } this.CurrentStream = File.Create(newFilename); + this.FileIsEmpty = true; } /// @@ -180,5 +200,23 @@ public override string TotalProcessed() { return $"{this.Processed}"; } + + /// + public override void Dispose() + { + base.Dispose(); + + // Disposing the stream can leave a zero-length file on disk if nothing + // was recorded into it -- but after recording has taken place, only + // calling NewFile (or Split for videos) will create a new empty file. + if (this.FileIsEmpty) + { + try + { + File.Delete(this.CurrentStream.Name); + } + catch { } + } + } } } diff --git a/src/MMALSharp.Processing/Handlers/VideoStreamCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/VideoStreamCaptureHandler.cs index 29c17bc9..662cbb20 100644 --- a/src/MMALSharp.Processing/Handlers/VideoStreamCaptureHandler.cs +++ b/src/MMALSharp.Processing/Handlers/VideoStreamCaptureHandler.cs @@ -76,8 +76,9 @@ public override void Process(ImageContext context) if (this.StoreVideoTimestamps && context.Pts.HasValue) { var str = $"{context.Pts / 1000}.{context.Pts % 1000:000}" + Environment.NewLine; - + File.AppendAllText($"{this.Directory}/{this.CurrentFilename}.pts", str); + this.FileIsEmpty = false; } } @@ -85,7 +86,7 @@ public override void Process(ImageContext context) /// Splits the current file by closing the current stream and opening a new one. /// public virtual void Split() => this.NewFile(); - + /// /// Used to set the current working motion vector store. ///