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;
}