Skip to content
This repository has been archived by the owner on Feb 22, 2024. It is now read-only.

Commit

Permalink
More unit test work for #9. Added GetCameraSettings method to assist …
Browse files Browse the repository at this point in the history
…with getting exposure and gains. Updated README.
  • Loading branch information
techyian committed May 1, 2017
1 parent d0e232d commit bf48c68
Show file tree
Hide file tree
Showing 22 changed files with 207 additions and 1,005 deletions.
57 changes: 3 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,9 @@ MMALSharp supports the following runtimes:
1) Mono 4.x
2) .NET Core 2.0 (beta) with .NET Standard 1.6.

## Installation

For full installation instructions for Mono 4.x and .NET Core - please visit the [Documentation](https://techyian.github.io/MMALSharp) site

## Basic Usage

Using the library is relatively simple. If you want to change any of the default configuration settings, this can be done by modifying the
properties within `MMALCameraConfig`. The main class `MMALCamera` which interfaces to the rest of the functionality the library provides is
a Singleton and is called as follows: `MMALCamera cam = MMALCamera.Instance`.

MMALSharp is asynchronous in nature, preventing any blocking of the main thread in your application. From testing, I found it is important that we provide a context
for the asynchronous code to run in, this is because when we await processing to complete, we need to return to the same thread we began processing on.

Below is a basic example of its usage.

```
public static void Main(string[] args)
{
Alter any configuration properties required.
MMALCameraConfig.EnableAnnotate = true;
MMALCameraConfig.Annotate = new AnnotateImage { ShowDateText = true, ShowTimeText = true };
MMALCameraConfig.VideoHeight = 1024;
MMALCameraConfig.VideoWidth = 768;
//Required for segmented recording
MMALCameraConfig.InlineHeaders = true;
MMALCamera cam = MMALCamera.Instance;
AsyncContext.Run(async () =>
{
using (var vidEncoder = new MMALVideoEncoder(new VideoStreamCaptureHandler("/home/pi/videos", ".avi"), 40))
using (var imgEncoder = new MMALImageEncoder(new ImageStreamCaptureHandler("/home/pi/images/", "jpg")))
{
//Create our component pipeline.
cam.AddEncoder(vidEncoder, cam.Camera.VideoPort)
.AddEncoder(imgEncoder, cam.Camera.StillPort)
.CreatePreviewComponent(new MMALVideoRenderer())
.ConfigureCamera();
//Record video for 1 minute, using segmented video record to split into multiple files every 30 seconds.
await cam.TakeVideo(cam.Camera.VideoPort, DateTime.Now.AddMinutes(1), new Split { Mode = TimelapseMode.Second, Value = 30 });
//Take a single picture on the camera's still port using the encoder connected to the still port
await cam.TakePicture(cam.Camera.StillPort);
}
//Once we're finished with the camera and will *not* use it again, cleanup any unmanaged resources.
cam.Cleanup();
});
}
```
## Documentation

For full installation instructions for Mono 4.x and .NET Core, including configuration and examples - please visit the [Documentation](https://techyian.github.io/MMALSharp) site.

## Status

Expand Down
8 changes: 8 additions & 0 deletions docfx/articles/examples.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Examples

If you want to change any of the default configuration settings, this can be done by modifying the
static properties within the `MMALCameraConfig` class. The main class, `MMALCamera` which interfaces to the rest of the functionality the library provides is
a Singleton and is called as follows: `MMALCamera cam = MMALCamera.Instance`.

MMALSharp is asynchronous in nature, preventing any blocking of the main thread in your application. If you are planning on using MMALSharp within a console
application, it is important to provide a context which your application will use when returning from asynchronous method calls. In the examples below, we
are demonstrating usage with `AsyncContext` included in the `Nito.AsyncEx` library by [@StephenClary](https://github.com/StephenCleary/AsyncEx). GUI applications provide their own context and therefore this should not be necessary.

## Image capture

### Simple JPEG capture
Expand Down
8 changes: 7 additions & 1 deletion docs/articles/examples.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@
<article class="content wrap" id="_content" data-uid="">
<h1 id="examples">Examples</h1>

<p>If you want to change any of the default configuration settings, this can be done by modifying the
static properties within the <code>MMALCameraConfig</code> class. The main class, <code>MMALCamera</code> which interfaces to the rest of the functionality the library provides is
a Singleton and is called as follows: <code>MMALCamera cam = MMALCamera.Instance</code>.</p>
<p>MMALSharp is asynchronous in nature, preventing any blocking of the main thread in your application. If you are planning on using MMALSharp within a console
application, it is important to provide a context which your application will use when returning from asynchronous method calls. In the examples below, we
are demonstrating usage with <code>AsyncContext</code> included in the <code>Nito.AsyncEx</code> library by <a href="https://github.com/StephenCleary/AsyncEx">@StephenClary</a>. GUI applications provide their own context and therefore this should not be necessary.</p>
<h2 id="image-capture">Image capture</h2>
<h3 id="simple-jpeg-capture">Simple JPEG capture</h3>
<pre><code>
Expand Down Expand Up @@ -359,7 +365,7 @@ <h3 id="rtmp-streaming">RTMP streaming</h3>
<div class="contribution">
<ul class="nav">
<li>
<a href="https://github.com/techyian/MMALSharp/blob/master/docfx/articles/examples.md/#L1" class="contribution-link">Improve this Doc</a>
<a href="https://github.com/techyian/MMALSharp/blob/dev/docfx/articles/examples.md/#L1" class="contribution-link">Improve this Doc</a>
</li>
</ul>
</div>
Expand Down
3 changes: 1 addition & 2 deletions src/MMALSharp.Common/Handlers/StreamCaptureHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ public StreamCaptureHandler(string directory, string extension)
/// </summary>
public void NewFile()
{
if (this.CurrentStream != null)
this.CurrentStream.Dispose();
this.CurrentStream?.Dispose();

this.CurrentStream = File.Create(this.Directory + "/" + DateTime.Now.ToString("dd-MMM-yy HH-mm-ss") + "." + this.Extension);
}
Expand Down
3 changes: 1 addition & 2 deletions src/MMALSharp/Components/MMALCameraComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ public void CameraControlCallback(MMALBufferImpl buffer, MMALPortBase port)

public override void Dispose()
{
if (this.CameraInfo != null)
this.CameraInfo.DestroyComponent();
this.CameraInfo?.DestroyComponent();
base.Dispose();
}

Expand Down
7 changes: 2 additions & 5 deletions src/MMALSharp/Components/MMALComponentBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,8 @@ internal void DisableComponent()
public virtual void ManagedCallback(MMALBufferImpl buffer, MMALPortBase port)
{
var data = buffer.GetBufferData();

if (this.Handler != null)
{
this.Handler.Process(data);
}

this.Handler?.Process(data);
}

/// <summary>
Expand Down
25 changes: 7 additions & 18 deletions src/MMALSharp/MMALCamera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ 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}");
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;
Expand Down Expand Up @@ -203,7 +203,7 @@ 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}");
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);
}
Expand Down Expand Up @@ -294,10 +294,7 @@ private async Task BeginProcessing(MMALComponentBase component, MMALConnectionIm
component.Stop(outputPort);

//Close open connections.
if(connection != null)
{
connection.Disable();
}
connection?.Disable();

component.CleanPortPools();
}
Expand Down Expand Up @@ -381,7 +378,7 @@ public MMALCamera RemoveEncoder(MMALPortImpl outputPort)
public void DisableCamera()
{
this.Encoders.ForEach(c => c.DisableComponent());
this.Preview.DisableComponent();
this.Preview?.DisableComponent();
this.Camera.DisableComponent();
}

Expand All @@ -391,7 +388,7 @@ public void DisableCamera()
public void EnableCamera()
{
this.Encoders.ForEach(c => c.EnableComponent());
this.Preview.EnableComponent();
this.Preview?.EnableComponent();
this.Camera.EnableComponent();
}

Expand Down Expand Up @@ -464,16 +461,8 @@ public void Cleanup()
}

this.Encoders.ForEach(c => c.Dispose());

if (this.Preview != null)
{
this.Preview.Dispose();
}

if (this.Camera != null)
{
this.Camera.Dispose();
}
this.Preview?.Dispose();
this.Camera?.Dispose();

BcmHost.bcm_host_deinit();
}
Expand Down
4 changes: 2 additions & 2 deletions src/MMALSharp/MMALCameraConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ public static class MMALCameraConfig
/// <summary>
/// Adjust auto white balance 'red' gains
/// </summary>
public static int AwbGainsR { get; set; }
public static double AwbGainsR { get; set; }

/// <summary>
/// Adjust auto white balance 'blue' gains
/// </summary>
public static int AwbGainsB { get; set; }
public static double AwbGainsB { get; set; }

/// <summary>
/// Adjust dynamic range compression
Expand Down
19 changes: 15 additions & 4 deletions src/MMALSharp/MMALCameraExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ internal static void SetBrightness(this MMALCamera camera, double brightness)

public static int GetISO(this MMALCamera camera)
{
return camera.Camera.Control.GetParameter(MMAL_PARAMETER_ISO);
return (int)camera.Camera.Control.GetParameter(MMAL_PARAMETER_ISO);
}

internal static void SetISO(this MMALCamera camera, int iso)
Expand Down Expand Up @@ -230,10 +230,21 @@ internal static void SetAwbMode(this MMALCamera camera, MMAL_PARAM_AWBMODE_T mod
MMALCheck(MMALPort.mmal_port_parameter_set(camera.Camera.Control.Ptr, &awbMode.hdr), "Unable to set awb mode");
}

public static MMAL_PARAMETER_CAMERA_SETTINGS_T GetCameraSettings(this MMALCamera camera)
{
MMAL_PARAMETER_CAMERA_SETTINGS_T settings = new MMAL_PARAMETER_CAMERA_SETTINGS_T(new MMAL_PARAMETER_HEADER_T(MMAL_PARAMETER_CAMERA_SETTINGS, Marshal.SizeOf<MMAL_PARAMETER_CAMERA_SETTINGS_T>()),
0, new MMAL_RATIONAL_T(0, 0), new MMAL_RATIONAL_T(0, 0),
new MMAL_RATIONAL_T(0, 0), new MMAL_RATIONAL_T(0, 0), 0);

MMALCheck(MMALPort.mmal_port_parameter_get(camera.Camera.Control.Ptr, &settings.hdr), "Unable to get camera settings");

return settings;
}

public static Tuple<double, double> GetAwbGains(this MMALCamera camera)
{
MMAL_PARAMETER_AWB_GAINS_T awbGains = new MMAL_PARAMETER_AWB_GAINS_T(new MMAL_PARAMETER_HEADER_T(MMAL_PARAMETER_CUSTOM_AWB_GAINS, Marshal.SizeOf<MMAL_PARAMETER_AWB_GAINS_T>()),
new MMAL_RATIONAL_T(0, 0), new MMAL_RATIONAL_T(0, 0));
new MMAL_RATIONAL_T(0, 65536), new MMAL_RATIONAL_T(0, 65536));

MMALCheck(MMALPort.mmal_port_parameter_get(camera.Camera.Control.Ptr, &awbGains.hdr), "Unable to get awb gains");

Expand All @@ -253,7 +264,7 @@ internal static void SetAwbGains(this MMALCamera camera, double rGain, double bG

if (MMALCameraConfig.AwbMode != MMAL_PARAM_AWBMODE_T.MMAL_PARAM_AWBMODE_OFF && (rGain > 0 || bGain > 0))
throw new PiCameraError("AWB Mode must be off when setting AWB gains");

MMAL_PARAMETER_AWB_GAINS_T awbGains = new MMAL_PARAMETER_AWB_GAINS_T(new MMAL_PARAMETER_HEADER_T(MMAL_PARAMETER_CUSTOM_AWB_GAINS, Marshal.SizeOf<MMAL_PARAMETER_AWB_GAINS_T>()),
new MMAL_RATIONAL_T((int)(rGain * 65536), 65536),
new MMAL_RATIONAL_T((int)(bGain * 65536), 65536));
Expand Down Expand Up @@ -365,7 +376,7 @@ internal static void SetZoom(this MMALCamera camera, Zoom rect)

public static int GetShutterSpeed(this MMALCamera camera)
{
return camera.Camera.Control.GetParameter(MMAL_PARAMETER_SHUTTER_SPEED);
return (int)camera.Camera.Control.GetParameter(MMAL_PARAMETER_SHUTTER_SPEED);
}

internal static void SetShutterSpeed(this MMALCamera camera, int speed)
Expand Down
6 changes: 3 additions & 3 deletions src/MMALSharp/MMALPortBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ internal void SendBuffer(MMALBufferImpl buffer)
/// </summary>
internal void DestroyPortPool()
{
if(this.BufferPool != null)
if (this.BufferPool != null)
{
MMALUtil.mmal_port_pool_destroy(this.Ptr, this.BufferPool.Ptr);
}
}


}
}
23 changes: 0 additions & 23 deletions src/MMALSharpCoreExample/MMALSharpCoreExample.csproj

This file was deleted.

90 changes: 0 additions & 90 deletions src/MMALSharpCoreExample/Program.cs

This file was deleted.

Loading

0 comments on commit bf48c68

Please sign in to comment.