diff --git a/src/devices/Camera/Camera/Settings/Command.cs b/src/devices/Camera/Camera/Settings/Command.cs index d7e7890fc5..1c112390c7 100644 --- a/src/devices/Camera/Camera/Settings/Command.cs +++ b/src/devices/Camera/Camera/Settings/Command.cs @@ -399,4 +399,9 @@ public enum Command /// The command for the --frames option /// Frames, + + /// + /// The command for the --framerate option + /// + Framerate, } diff --git a/src/devices/Camera/Camera/Settings/CommandOptionsBuilder.cs b/src/devices/Camera/Camera/Settings/CommandOptionsBuilder.cs index a95711f951..cc92781f4b 100644 --- a/src/devices/Camera/Camera/Settings/CommandOptionsBuilder.cs +++ b/src/devices/Camera/Camera/Settings/CommandOptionsBuilder.cs @@ -255,6 +255,40 @@ public CommandOptionsBuilder WithMJPEGVideoOptions(int quality) return this; } + /// + /// Adds the option to capture a video stream at a certain Framerate. + /// + /// The number of frames per second, if not specified uses the camera default + /// A reference to this instance. + public CommandOptionsBuilder WithVideoFramerate(int rate) + { + AddFramerate(rate); + return this; + } + + /// + /// Adds the option to load a tuning file for the camera + /// + /// The path to the tuning file. + /// A reference to this instance. + public CommandOptionsBuilder WithTuningFile(string path) + { + AddTuningFile(path); + return this; + } + + private void AddFramerate(int rate) + { + var cmd = GetByCategory(CommandCategory.Video, Command.Framerate); + _commands.Add(new CommandOptionAndValue(cmd, rate.ToString())); + } + + private void AddTuningFile(string path) + { + var cmd = Get(Command.TuningFile); + _commands.Add(new CommandOptionAndValue(cmd, path)); + } + private void AddListCameras() { var cmd = Get(Command.ListCameras); diff --git a/src/devices/Camera/Camera/Settings/LibcameraAppsSettings.cs b/src/devices/Camera/Camera/Settings/LibcameraAppsSettings.cs index a235562328..7d6b21c727 100644 --- a/src/devices/Camera/Camera/Settings/LibcameraAppsSettings.cs +++ b/src/devices/Camera/Camera/Settings/LibcameraAppsSettings.cs @@ -305,5 +305,9 @@ public class LibcameraAppsSettings new CommandOption(CommandCategory.Video, Command.Frames, "--frames", "Record exactly this many frames ", CommandInputType.Int), + + new CommandOption(CommandCategory.Video, Command.Framerate, + "--framerate", "Set the frames per second captured ", CommandInputType.Int), + }; } diff --git a/src/devices/Camera/samples/Camera.Samples/Capture.cs b/src/devices/Camera/samples/Camera.Samples/Capture.cs index 3c38896b88..cbb0b04438 100644 --- a/src/devices/Camera/samples/Camera.Samples/Capture.cs +++ b/src/devices/Camera/samples/Camera.Samples/Capture.cs @@ -113,7 +113,7 @@ public async Task CaptureTimelapse() // The ContinuousRunAsync method offload the capture on a separate thread // the first await is tied the thread being run // the second await is tied to the capture - var task = await proc.ContinuousRunAsync(args, null); + var task = await proc.ContinuousRunAsync(args, default(Stream)); await task; } diff --git a/src/devices/Common/Iot/Device/Common/ProcessRunner.cs b/src/devices/Common/Iot/Device/Common/ProcessRunner.cs index 5f795918c8..f4ebda0d8e 100644 --- a/src/devices/Common/Iot/Device/Common/ProcessRunner.cs +++ b/src/devices/Common/Iot/Device/Common/ProcessRunner.cs @@ -55,11 +55,11 @@ public void Kill() { if (_process != null && !_process.HasExited) { -#if NETSTANDARD2_0 + #if NETSTANDARD2_0 _process.Kill(); -#else + #else _process.Kill(true); -#endif + #endif if (!_process.HasExited) { _process.WaitForExit(5000); @@ -129,11 +129,11 @@ public async Task ExecuteAsync(string argsString, Stream? target) if (target == null) { -#if NETSTANDARD2_0 + #if NETSTANDARD2_0 _process.WaitForExit(); -#else + #else await _process.WaitForExitAsync(_cts.Token); -#endif + #endif return; } @@ -145,11 +145,10 @@ public async Task ExecuteAsync(string argsString, Stream? target) { await _process.StandardOutput.BaseStream.CopyToAsync(target, _processSettings.BufferSize, _cts.Token); } - - _process.WaitForExit(_processSettings.MaxMillisecondsToWaitAfterProcessCompletes); } finally { + _process?.WaitForExit(_processSettings.MaxMillisecondsToWaitAfterProcessCompletes); _process?.Dispose(); _process = null; } @@ -213,6 +212,34 @@ public async Task ContinuousRunAsync(string argsString, Stream? target) }, _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); } + /// + /// Runs the execute on a separate thread + /// + /// The array of command line arguments. + /// The pipe that will receive the output of the process. + /// A task that represent the new thread communicating with the process. + /// The returned value is the task that represents the output being copied to the target pipe + public Task ContinuousRunAsync(string[] arguments, PipeWriter target) + { + var argsString = string.Join(" ", arguments); + return ContinuousRunAsync(argsString, target); + } + + /// + /// Runs the execute on a separate thread + /// + /// A string will the complete command line of the process. + /// The pipe that will receive the output of the process. + /// A task that represent the new thread communicating with the process. + /// The returned value is the task that represents the output being copied to the target pipe + public async Task ContinuousRunAsync(string argsString, PipeWriter target) + { + return await Task.Factory.StartNew(async () => + { + await ExecuteAsync(argsString, target); + }, _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + } + /// /// Execute the process with a number of arguments. The target Pipe /// receive the stdout of the process @@ -243,6 +270,7 @@ public async Task ExecuteAsync(string argsString, PipeWriter target) } finally { + _process?.WaitForExit(_processSettings.MaxMillisecondsToWaitAfterProcessCompletes); _process?.Dispose(); _process = null; }