diff --git a/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs b/src/MMALSharp.Processing/Handlers/CircularBufferCaptureHandler.cs index 43ffa50a..574ae376 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; @@ -85,6 +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); + this.FileIsEmpty = false; } this.Processed += this.Buffer.Size; @@ -94,6 +96,7 @@ public override void Process(ImageContext context) if (this.CurrentStream != null && this.CurrentStream.CanWrite) { this.CurrentStream.Write(context.Data, 0, context.Data.Length); + this.FileIsEmpty = false; } this.Processed += context.Data.Length; @@ -154,12 +157,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..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; @@ -36,10 +37,16 @@ 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; } + /// + /// 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; } /// @@ -63,9 +73,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}"; @@ -80,6 +90,7 @@ public FileStreamCaptureHandler(string directory, string extension) this.CurrentFilename = Path.GetFileNameWithoutExtension(fileInfo.Name); this.CurrentStream = File.Create(fileName); + this.FileIsEmpty = true; } /// @@ -94,12 +105,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}"); @@ -109,17 +120,25 @@ 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; } /// - /// 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() => @@ -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. ///