diff --git a/src/MMALSharp/Components/MMALCameraComponent.cs b/src/MMALSharp/Components/MMALCameraComponent.cs
index a1c31d6d..9ef41327 100644
--- a/src/MMALSharp/Components/MMALCameraComponent.cs
+++ b/src/MMALSharp/Components/MMALCameraComponent.cs
@@ -136,7 +136,7 @@ internal void Initialise()
this.InitialiseStill();
}
- private void InitialisePreview()
+ internal void InitialisePreview()
{
var vFormat = new MMAL_VIDEO_FORMAT_T(
MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.VideoResolution.Width, 32),
@@ -157,7 +157,7 @@ private void InitialisePreview()
this.PreviewPort.Commit();
}
- private void InitialiseVideo()
+ internal void InitialiseVideo()
{
if (MMALCameraConfig.VideoResolution.Width == 0 || MMALCameraConfig.VideoResolution.Width > this.CameraInfo.MaxWidth)
{
@@ -194,7 +194,7 @@ private void InitialiseVideo()
this.VideoPort.BufferSizeMin);
}
- private void InitialiseStill()
+ internal void InitialiseStill()
{
//If user hasn't specified Width/Height, or one which is too high, use highest resolution supported by sensor.
if (MMALCameraConfig.StillResolution == null)
@@ -218,13 +218,12 @@ private void InitialiseStill()
MMALCameraConfig.StillEncoding == MMALEncoding.MMAL_ENCODING_RGB24 ||
MMALCameraConfig.StillEncoding == MMALEncoding.MMAL_ENCODING_RGB16)
{
- Helpers.PrintWarning("Encoding set to RGB. Increasing width padding to multiple of 16.");
+ Helpers.PrintWarning("Encoding set to RGB. Setting width padding to multiple of 16.");
vFormat = new MMAL_VIDEO_FORMAT_T(
MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Width, 16),
MMALUtil.VCOS_ALIGN_UP(MMALCameraConfig.StillResolution.Height, 16),
- new MMAL_RECT_T(0, 0, MMALCameraConfig.StillResolution.Width,
- MMALCameraConfig.StillResolution.Height),
+ new MMAL_RECT_T(0, 0, MMALCameraConfig.StillResolution.Width, MMALCameraConfig.StillResolution.Height),
new MMAL_RATIONAL_T(0, 1),
this.StillPort.Ptr->Format->es->video.Par,
this.StillPort.Ptr->Format->es->video.ColorSpace
@@ -242,14 +241,14 @@ private void InitialiseStill()
this.StillPort.Ptr->Format->es->video.ColorSpace
);
}
-
+
this.StillPort.Ptr->Format->es->video = vFormat;
this.StillPort.Ptr->Format->encoding = MMALCameraConfig.StillEncoding.EncodingVal;
this.StillPort.Ptr->Format->encodingVariant = MMALCameraConfig.StillSubFormat.EncodingVal;
if (MMALCameraConfig.Debug)
Console.WriteLine("Commit still");
-
+
this.StillPort.Commit();
this.StillPort.Ptr->BufferNum = Math.Max(this.StillPort.BufferNumRecommended,
diff --git a/src/MMALSharp/Components/MMALComponentBase.cs b/src/MMALSharp/Components/MMALComponentBase.cs
index 70c2c393..71ee788a 100644
--- a/src/MMALSharp/Components/MMALComponentBase.cs
+++ b/src/MMALSharp/Components/MMALComponentBase.cs
@@ -220,6 +220,9 @@ internal void CleanPortPools()
if (MMALCameraConfig.Debug)
Console.WriteLine("Destroying port pool");
+ if (port.Enabled)
+ port.DisablePort();
+
port.DestroyPortPool();
port.BufferPool = null;
}
@@ -232,6 +235,9 @@ internal void CleanPortPools()
if (MMALCameraConfig.Debug)
Console.WriteLine("Destroying port pool");
+ if (port.Enabled)
+ port.DisablePort();
+
port.DestroyPortPool();
port.BufferPool = null;
}
diff --git a/src/MMALSharp/MMALCamera.cs b/src/MMALSharp/MMALCamera.cs
index 839f02e4..3dfb7495 100644
--- a/src/MMALSharp/MMALCamera.cs
+++ b/src/MMALSharp/MMALCamera.cs
@@ -112,7 +112,8 @@ public async Task TakeVideo(MMALPortImpl connPort, DateTime? timeout = null, Spl
try
{
- Console.WriteLine($"Preparing to take video. Resolution: {MMALCameraConfig.VideoResolution.Width} x {MMALCameraConfig.VideoResolution.Height}. Encoder: {encoder.EncodingType.EncodingName}. Pixel Format: {encoder.PixelFormat.EncodingName}.");
+ Console.WriteLine($"Preparing to take video. Resolution: {MMALCameraConfig.VideoResolution.Width} x {MMALCameraConfig.VideoResolution.Height}. " +
+ $"Encoder: {encoder.EncodingType.EncodingName}. Pixel Format: {encoder.PixelFormat.EncodingName}.");
((MMALVideoPort)encoder.Outputs.ElementAt(0)).Timeout = timeout;
((MMALVideoEncoder)encoder).Split = split;
@@ -138,19 +139,16 @@ public async Task TakeRawPicture(ICaptureHandler handler)
{
throw new PiCameraError("A connection was found to the Camera still port. No encoder should be connected to the Camera's still port for raw capture.");
}
- if (handler == null)
- {
- throw new PiCameraError("No handler specified");
- }
- this.Camera.Handler = handler;
+ this.Camera.Handler = handler ?? throw new PiCameraError("No handler specified");
this.CheckPreviewComponentStatus();
//Enable the image encoder output port.
try
{
- Console.WriteLine($"Preparing to take picture - Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}");
+ Console.WriteLine($"Preparing to take raw picture - Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}. " +
+ $"Encoder: {MMALCameraConfig.StillEncoding.EncodingName}. Pixel Format: {MMALCameraConfig.StillSubFormat.EncodingName}.");
await BeginProcessing(this.Camera, null, this.Camera.StillPort, MMALCameraComponent.MMALCameraStillPort);
}
@@ -209,7 +207,8 @@ public async Task TakePicture(MMALPortImpl connPort, bool rawBayer = false, bool
//Enable the image encoder output port.
try
{
- Console.WriteLine($"Preparing to take picture. Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}. Encoder: {encoder.EncodingType.EncodingName}. Pixel Format: {encoder.PixelFormat.EncodingName}.");
+ Console.WriteLine($"Preparing to take picture. Resolution: {MMALCameraConfig.StillResolution.Width} x {MMALCameraConfig.StillResolution.Height}. " +
+ $"Encoder: {encoder.EncodingType.EncodingName}. Pixel Format: {encoder.PixelFormat.EncodingName}.");
await BeginProcessing(encoder, encoder.Connection, this.Camera.StillPort, 0);
}
@@ -228,8 +227,13 @@ public async Task TakePicture(MMALPortImpl connPort, bool rawBayer = false, bool
/// Specify whether to include EXIF tags in the capture
/// Custom EXIF tags to use in the capture
/// The awaitable Task
- public async Task TakePictureTimeout(MMALPortImpl connPort, DateTime timeout, bool rawBayer = false, bool useExif = true, params ExifTag[] exifTags)
- {
+ public async Task TakePictureTimeout(MMALPortImpl connPort, DateTime timeout, bool rawBayer = false, bool useExif = true, bool burstMode = false, params ExifTag[] exifTags)
+ {
+ if(burstMode)
+ {
+ this.Camera.StillPort.SetParameter(MMALParametersCamera.MMAL_PARAMETER_CAMERA_BURST_CAPTURE, true);
+ }
+
while (DateTime.Now.CompareTo(timeout) < 0)
{
await TakePicture(connPort, rawBayer, useExif, exifTags);
@@ -305,19 +309,16 @@ private async Task BeginProcessing(MMALComponentBase component, MMALConnectionIm
component.CleanPortPools();
}
+
+
///
/// Helper method to create a new preview component
///
/// The renderer type
- /// The static Camera instance
+ /// The camera instance
public MMALCamera CreatePreviewComponent(MMALRendererBase renderer)
{
- if (this.Preview != null)
- {
- this.Preview?.Connection.Disable();
- this.Preview?.Connection.Destroy();
- this.Preview.Dispose();
- }
+ this.DestroyPreviewComponent();
this.Preview = renderer;
this.Preview.CreateConnection(this.Camera.PreviewPort);
@@ -327,7 +328,7 @@ public MMALCamera CreatePreviewComponent(MMALRendererBase renderer)
///
/// Helper method to create a splitter component
///
- /// The static Camera instance
+ /// The camera instance
public MMALCamera CreateSplitterComponent()
{
this.Splitter = new MMALSplitterComponent();
@@ -339,7 +340,7 @@ public MMALCamera CreateSplitterComponent()
///
/// The encoder component to attach to the output port
/// The output port to attach to
- /// The static Camera instance
+ /// The camera instance
public MMALCamera AddEncoder(MMALEncoderBase encoder, MMALPortImpl outputPort)
{
if (MMALCameraConfig.Debug)
@@ -359,7 +360,7 @@ public MMALCamera AddEncoder(MMALEncoderBase encoder, MMALPortImpl outputPort)
/// Remove an encoder component from an output port
///
/// The output port we are removing an encoder component from
- /// The static Camera instance
+ /// The camera instance
public MMALCamera RemoveEncoder(MMALPortImpl outputPort)
{
var enc = this.Encoders.Where(c => c.Connection != null && c.Connection.OutputPort == outputPort).FirstOrDefault();
@@ -399,26 +400,76 @@ public void EnableCamera()
}
///
- /// Configures the camera component. This method applies configuration settings and initialises the components required
- /// for capturing images.
+ /// Reconfigures the Camera's still port.
///
- /// The static Camera instance
- public MMALCamera ConfigureCamera()
+ /// The camera instance
+ public MMALCamera ConfigureStill()
{
- if (MMALCameraConfig.Debug)
- {
- Console.WriteLine("Configuring camera parameters.");
- }
-
this.DisableCamera();
- this.Camera.SetCameraParameters();
+ this.Encoders.Where(c => c.Connection != null && c.Connection.OutputPort == this.Camera.StillPort).ToList().ForEach(c => c.Connection.Disable());
+
+ this.Camera.InitialiseStill();
+
+ this.Encoders.Where(c => c.Connection != null && c.Connection.OutputPort == this.Camera.StillPort).ToList().ForEach(c => c.Connection.Enable());
this.EnableCamera();
-
+
+ return this;
+ }
+
+ ///
+ /// Reconfigures the Camera's video port.
+ ///
+ /// The camera instance
+ public MMALCamera ConfigureVideo()
+ {
+ this.DisableCamera();
+
+ this.Encoders.Where(c => c.Connection != null && c.Connection.OutputPort == this.Camera.VideoPort).ToList().ForEach(c => c.Connection.Disable());
+
+ this.Camera.InitialiseVideo();
+
+ this.Encoders.Where(c => c.Connection != null && c.Connection.OutputPort == this.Camera.VideoPort).ToList().ForEach(c => c.Connection.Enable());
+
+ this.EnableCamera();
+
+ return this;
+ }
+
+ ///
+ /// Reconfigures the Camera's preview port.
+ ///
+ /// The camera instance
+ public MMALCamera ConfigurePreview()
+ {
+ this.DisableCamera();
+
+ this.Preview?.Connection?.Disable();
+ this.Camera.InitialisePreview();
+ this.Preview?.Connection?.Enable();
+
+ this.EnableCamera();
+
return this;
}
-
+
+
+ private void DestroyPreviewComponent()
+ {
+ if (this.Preview != null)
+ {
+ this.Preview?.Connection.Disable();
+ this.Preview?.Connection.Destroy();
+ this.Preview.Dispose();
+ }
+ }
+
+ private void DestroyEncoders()
+ {
+ this.Encoders.ForEach(c => c.Dispose());
+ }
+
///
/// Helper method to check the Renderer component status. If a Renderer has not been initialized, a warning will
/// be shown to the user. If a Renderer has been created but a connection has not been initialized, this will be
diff --git a/src/MMALSharp/MMALCameraConfig.cs b/src/MMALSharp/MMALCameraConfig.cs
index a0b9c3b3..c801fb6c 100644
--- a/src/MMALSharp/MMALCameraConfig.cs
+++ b/src/MMALSharp/MMALCameraConfig.cs
@@ -184,7 +184,7 @@ public static class MMALCameraConfig
///
public static void Reload()
{
- MMALCamera.Instance.ConfigureCamera();
+ MMALCamera.Instance.Camera.SetCameraParameters();
}
}
diff --git a/src/MMALSharp/MMALPortBase.cs b/src/MMALSharp/MMALPortBase.cs
index c2d1ba29..d9ae6e0d 100644
--- a/src/MMALSharp/MMALPortBase.cs
+++ b/src/MMALSharp/MMALPortBase.cs
@@ -218,6 +218,9 @@ internal void DestroyPortPool()
{
if (this.BufferPool != null)
{
+ if (this.Enabled)
+ this.DisablePort();
+
MMALUtil.mmal_port_pool_destroy(this.Ptr, this.BufferPool.Ptr);
}
}
diff --git a/src/MMALSharp/Native/MMALFormat.cs b/src/MMALSharp/Native/MMALFormat.cs
index 1f3ff8a9..cac3d1a9 100644
--- a/src/MMALSharp/Native/MMALFormat.cs
+++ b/src/MMALSharp/Native/MMALFormat.cs
@@ -112,11 +112,15 @@ public MMAL_SUBPICTURE_FORMAT_T(uint xOffset, uint yOffset)
}
}
- [StructLayout(LayoutKind.Sequential)]
+ //Union type.
+ [StructLayout(LayoutKind.Explicit)]
public struct MMAL_ES_SPECIFIC_FORMAT_T
{
+ [FieldOffset(0)]
public MMAL_AUDIO_FORMAT_T audio;
+ [FieldOffset(0)]
public MMAL_VIDEO_FORMAT_T video;
+ [FieldOffset(0)]
public MMAL_SUBPICTURE_FORMAT_T subpicture;
public MMAL_ES_SPECIFIC_FORMAT_T(MMAL_AUDIO_FORMAT_T audio, MMAL_VIDEO_FORMAT_T video, MMAL_SUBPICTURE_FORMAT_T subpicture)
diff --git a/tests/MMALSharp.Tests/ImageEncoderTests.cs b/tests/MMALSharp.Tests/ImageEncoderTests.cs
index 44efd8a2..a59f7ab1 100644
--- a/tests/MMALSharp.Tests/ImageEncoderTests.cs
+++ b/tests/MMALSharp.Tests/ImageEncoderTests.cs
@@ -348,9 +348,8 @@ public void TakePicture(string extension, MMALEncoding encodingType, MMALEncodin
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
-
+ .CreatePreviewComponent(new MMALNullSinkComponent());
+
await fixture.MMALCamera.TakePicture(fixture.MMALCamera.Camera.StillPort);
}
@@ -381,8 +380,7 @@ public void TakePictureRawBayer(string extension, MMALEncoding encodingType, MMA
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALNullSinkComponent());
await fixture.MMALCamera.TakePicture(fixture.MMALCamera.Camera.StillPort, true);
}
@@ -414,8 +412,7 @@ public void TakePictureTimelapse(string extension, MMALEncoding encodingType, MM
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALNullSinkComponent());
await fixture.MMALCamera.TakePictureTimelapse(fixture.MMALCamera.Camera.StillPort,
new Timelapse { Mode = TimelapseMode.Second, Value = 5, Timeout = DateTime.Now.AddSeconds(20) });
@@ -438,8 +435,7 @@ public void TakePictureTimeout(string extension, MMALEncoding encodingType, MMAL
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALNullSinkComponent());
await fixture.MMALCamera.TakePictureTimeout(fixture.MMALCamera.Camera.StillPort, DateTime.Now.AddSeconds(20));
@@ -462,8 +458,7 @@ public void ChangeEncodingType()
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALNullSinkComponent());
await fixture.MMALCamera.TakePicture(fixture.MMALCamera.Camera.StillPort);
}
@@ -485,8 +480,7 @@ public void ChangeEncodingType()
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(imgEncoder, fixture.MMALCamera.Camera.StillPort)
- .CreatePreviewComponent(new MMALNullSinkComponent())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALNullSinkComponent());
await fixture.MMALCamera.TakePicture(fixture.MMALCamera.Camera.StillPort);
}
diff --git a/tests/MMALSharp.Tests/VideoEncoderTests.cs b/tests/MMALSharp.Tests/VideoEncoderTests.cs
index 146a0a70..3d9c8f63 100644
--- a/tests/MMALSharp.Tests/VideoEncoderTests.cs
+++ b/tests/MMALSharp.Tests/VideoEncoderTests.cs
@@ -83,8 +83,7 @@ public void TakeVideo(string extension, MMALEncoding encodingType, MMALEncoding
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(vidEncoder, fixture.MMALCamera.Camera.VideoPort)
- .CreatePreviewComponent(new MMALVideoRenderer())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALVideoRenderer());
//Record video for 20 seconds
await fixture.MMALCamera.TakeVideo(fixture.MMALCamera.Camera.VideoPort, DateTime.Now.AddSeconds(20));
@@ -120,8 +119,7 @@ public void TakeVideoSplit(string extension, MMALEncoding encodingType, MMALEnco
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(vidEncoder, fixture.MMALCamera.Camera.VideoPort)
- .CreatePreviewComponent(new MMALVideoRenderer())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALVideoRenderer());
//2 files should be created from this test.
await fixture.MMALCamera.TakeVideo(fixture.MMALCamera.Camera.VideoPort, DateTime.Now.AddSeconds(30),
@@ -149,8 +147,7 @@ public void ChangeEncoderType()
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(vidEncoder, fixture.MMALCamera.Camera.VideoPort)
- .CreatePreviewComponent(new MMALVideoRenderer())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALVideoRenderer());
//Record video for 20 seconds
await fixture.MMALCamera.TakeVideo(fixture.MMALCamera.Camera.VideoPort, DateTime.Now.AddSeconds(20));
@@ -174,8 +171,7 @@ public void ChangeEncoderType()
//Create our component pipeline.
fixture.MMALCamera
.AddEncoder(vidEncoder, fixture.MMALCamera.Camera.VideoPort)
- .CreatePreviewComponent(new MMALVideoRenderer())
- .ConfigureCamera();
+ .CreatePreviewComponent(new MMALVideoRenderer());
//Record video for 20 seconds
await fixture.MMALCamera.TakeVideo(fixture.MMALCamera.Camera.VideoPort, DateTime.Now.AddSeconds(20));