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

Commit

Permalink
#47. Add rawcam port configuration types.
Browse files Browse the repository at this point in the history
  • Loading branch information
techyian committed Jan 19, 2020
1 parent bcf6ea3 commit 610ba75
Show file tree
Hide file tree
Showing 5 changed files with 414 additions and 20 deletions.
158 changes: 158 additions & 0 deletions src/MMALSharp/Components/MMALRawcamComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// <copyright file="MMALRawcamComponent.cs" company="Techyian">
// Copyright (c) Ian Auty. All rights reserved.
// Licensed under the MIT License. Please see LICENSE.txt for License info.
// </copyright>

using MMALSharp.Ports.Inputs;
using MMALSharp.Native;
using System;
using MMALSharp.Ports.Outputs;
using MMALSharp.Ports;
using MMALSharp.Handlers;
using System.Runtime.InteropServices;
using MMALSharp.Common.Utility;
using Microsoft.Extensions.Logging;
using static MMALSharp.MMALNativeExceptionHelper;
using static MMALSharp.Native.MMALParameters;

namespace MMALSharp.Components
{
/// <summary>
/// ----------------------------------------------------------------------------------------
/// PLEASE NOTE: THIS IS AN EXPERIMENTAL COMPONENT AND IS NOT BASED ON PRODUCTION READY CODE - https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=109137.
/// ----------------------------------------------------------------------------------------
/// This component interfaces directly to the camera receiver peripheral to
/// pass the image data and metadata that is received over CSI, CCP2, or CPI.
/// It does not use the ISP or the VPU to perform any form of processing on the image.
/// There are a few options within the peripheral for converting between Bayer
/// bit depths, and packing/unpacking DPCM data - that functionality is exposed.
/// https://github.com/raspberrypi/firmware/blob/master/documentation/ilcomponents/rawcam.html
/// </summary>
public class MMALRawcamComponent : MMALDownstreamHandlerComponent
{
/// <summary>
/// Creates a new instance of the <see cref="MMALRawcamComponent"/> class.
/// </summary>
public unsafe MMALRawcamComponent()
: base(MMAL_COMPONENT_RAWCAM)
{
// Default to use still image port behaviour.
this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid()));
this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[0])), this, Guid.NewGuid()));
}

/// <summary>
/// Creates a new instance of the <see cref="MMALRawcamComponent"/> class.
/// </summary>
/// <param name="outputPortType">The user defined output port type.</param>
public unsafe MMALRawcamComponent(Type outputPortType)
: base(MMAL_COMPONENT_RAWCAM)
{
this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid()));
this.Outputs.Add((IOutputPort)Activator.CreateInstance(outputPortType, (IntPtr)(&(*this.Ptr->Output[0])), this, Guid.NewGuid()));
}

/// <inheritdoc />
public override IDownstreamComponent ConfigureOutputPort(int outputPort, IMMALPortConfig config, IOutputCaptureHandler handler)
{
if (config is MMALRawcamPortConfig)
{
var rawcamConfig = config as MMALRawcamPortConfig;

this.ConfigureCameraInterface(rawcamConfig.CameraInterface);
this.ConfigureCameraClockingMode(rawcamConfig.ClockingMode);
this.ConfigureCameraRxConfig(rawcamConfig.RxConfig);
this.ConfigureTimingRegisters(rawcamConfig.TimingConfig);
}
else
{
MMALLog.Logger.LogWarning($"Rawcam component should be given port configuration of type {nameof(MMALRawcamPortConfig)}. Defaults will be used.");
}

return base.ConfigureOutputPort(outputPort, config, handler);
}

private unsafe void ConfigureCameraInterface(MMAL_CAMERA_INTERFACE_T cameraInterface)
{
MMAL_PARAMETER_CAMERA_INTERFACE_T param = new MMAL_PARAMETER_CAMERA_INTERFACE_T(new MMAL_PARAMETER_HEADER_T(MMALParametersCamera.MMAL_PARAMETER_CAMERA_INTERFACE, Marshal.SizeOf<MMAL_PARAMETER_CAMERA_INTERFACE_T>()), cameraInterface);

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(param));

Marshal.StructureToPtr(param, ptr, false);

try
{
MMALCheck(
MMALPort.mmal_port_parameter_set(this.Inputs[0].Ptr, (MMAL_PARAMETER_HEADER_T*)ptr),
"Unable to set camera interface type.");
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}

private unsafe void ConfigureCameraClockingMode(MMAL_CAMERA_CLOCKING_MODE_T clockingMode)
{
MMAL_PARAMETER_CAMERA_CLOCKING_MODE_T param = new MMAL_PARAMETER_CAMERA_CLOCKING_MODE_T(new MMAL_PARAMETER_HEADER_T(MMALParametersCamera.MMAL_PARAMETER_CAMERA_CLOCKING_MODE, Marshal.SizeOf<MMAL_PARAMETER_CAMERA_CLOCKING_MODE_T>()), clockingMode);

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(param));

Marshal.StructureToPtr(param, ptr, false);

try
{
MMALCheck(
MMALPort.mmal_port_parameter_set(this.Inputs[0].Ptr, (MMAL_PARAMETER_HEADER_T*)ptr),
"Unable to set camera clocking mode.");
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}

private unsafe void ConfigureCameraRxConfig(MMALRawcamRxConfig rxConfig)
{
MMAL_PARAMETER_CAMERA_RX_CONFIG_T param = new MMAL_PARAMETER_CAMERA_RX_CONFIG_T(new MMAL_PARAMETER_HEADER_T(MMALParametersCamera.MMAL_PARAMETER_CAMERA_RX_CONFIG, Marshal.SizeOf<MMAL_PARAMETER_CAMERA_RX_CONFIG_T>()), rxConfig.DecodeConfig,
rxConfig.EncodeConfig, rxConfig.UnpackConfig, rxConfig.PackConfig, rxConfig.DataLanes, rxConfig.EncodeBlockLength, rxConfig.EmbeddedDataLines, rxConfig.ImageId);

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(param));

Marshal.StructureToPtr(param, ptr, false);

try
{
MMALCheck(
MMALPort.mmal_port_parameter_set(this.Inputs[0].Ptr, (MMAL_PARAMETER_HEADER_T*)ptr),
"Unable to set camera peripheral config.");
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}

private unsafe void ConfigureTimingRegisters(MMALRawcamTimingConfig timingConfig)
{
MMAL_PARAMETER_CAMERA_RX_TIMING_T param = new MMAL_PARAMETER_CAMERA_RX_TIMING_T(new MMAL_PARAMETER_HEADER_T(MMALParametersCamera.MMAL_PARAMETER_CAMERA_RX_TIMING, Marshal.SizeOf<MMAL_PARAMETER_CAMERA_RX_TIMING_T>()), timingConfig.Timing1,
timingConfig.Timing2, timingConfig.Timing3, timingConfig.Timing4, timingConfig.Timing5, timingConfig.Term1, timingConfig.Term2,
timingConfig.CpiTiming1, timingConfig.CpiTiming2);

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(param));

Marshal.StructureToPtr(param, ptr, false);

try
{
MMALCheck(
MMALPort.mmal_port_parameter_set(this.Inputs[0].Ptr, (MMAL_PARAMETER_HEADER_T*)ptr),
"Unable to set camera timing registers.");
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
}
40 changes: 20 additions & 20 deletions src/MMALSharp/Native/MMALParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1702,21 +1702,21 @@ public struct MMAL_PARAMETER_CAMERA_RX_CONFIG_T
private MMAL_CAMERA_RX_CONFIG_ENCODE encode;
private MMAL_CAMERA_RX_CONFIG_UNPACK unpack;
private MMAL_CAMERA_RX_CONFIG_PACK pack;
private uint dataLanes, encodeBlockLength, embeddedDataLines, imageId;
private int dataLanes, encodeBlockLength, embeddedDataLines, imageId;

public MMAL_CAMERA_RX_CONFIG_DECODE Decode => decode;
public MMAL_CAMERA_RX_CONFIG_ENCODE Encode => encode;
public MMAL_CAMERA_RX_CONFIG_UNPACK Unpack => unpack;
public MMAL_CAMERA_RX_CONFIG_PACK Pack => pack;
public uint DataLanes => dataLanes;
public uint EncodeBlockLength => encodeBlockLength;
public uint EmbeddedDataLanes => embeddedDataLines;
public uint ImageId => imageId;
public int DataLanes => dataLanes;
public int EncodeBlockLength => encodeBlockLength;
public int EmbeddedDataLanes => embeddedDataLines;
public int ImageId => imageId;

public MMAL_PARAMETER_CAMERA_RX_CONFIG_T(MMAL_PARAMETER_HEADER_T hdr, MMAL_CAMERA_RX_CONFIG_DECODE decode,
MMAL_CAMERA_RX_CONFIG_ENCODE encode, MMAL_CAMERA_RX_CONFIG_UNPACK unpack,
MMAL_CAMERA_RX_CONFIG_PACK pack,
uint dataLanes, uint encodeBlockLength, uint embeddedDataLines, uint imageId)
int dataLanes, int encodeBlockLength, int embeddedDataLines, int imageId)
{
this.Hdr = hdr;
this.decode = decode;
Expand All @@ -1734,20 +1734,20 @@ public MMAL_PARAMETER_CAMERA_RX_CONFIG_T(MMAL_PARAMETER_HEADER_T hdr, MMAL_CAMER
public struct MMAL_PARAMETER_CAMERA_RX_TIMING_T
{
public MMAL_PARAMETER_HEADER_T Hdr;
private uint timing1, timing2, timing3, timing4, timing5, term1, term2, cpiTiming1, cpiTiming2;
private int timing1, timing2, timing3, timing4, timing5, term1, term2, cpiTiming1, cpiTiming2;

public uint Timing1 => timing1;
public uint Timing2 => timing2;
public uint Timing3 => timing3;
public uint Timing4 => timing4;
public uint Timing5 => timing5;
public uint Term1 => term1;
public uint Term2 => term2;
public uint CpiTiming1 => cpiTiming1;
public uint CpiTiming2 => cpiTiming2;
public int Timing1 => timing1;
public int Timing2 => timing2;
public int Timing3 => timing3;
public int Timing4 => timing4;
public int Timing5 => timing5;
public int Term1 => term1;
public int Term2 => term2;
public int CpiTiming1 => cpiTiming1;
public int CpiTiming2 => cpiTiming2;

public MMAL_PARAMETER_CAMERA_RX_TIMING_T(MMAL_PARAMETER_HEADER_T hdr, uint timing1, uint timing2, uint timing3, uint timing4,
uint timing5, uint term1, uint term2, uint cpiTiming1, uint cpiTiming2)
public MMAL_PARAMETER_CAMERA_RX_TIMING_T(MMAL_PARAMETER_HEADER_T hdr, int timing1, int timing2, int timing3, int timing4,
int timing5, int term1, int term2, int cpiTiming1, int cpiTiming2)
{
this.Hdr = hdr;
this.timing1 = timing1;
Expand Down Expand Up @@ -2475,11 +2475,11 @@ public static class MMALParameters
public const string MMAL_COMPONENT_DEFAULT_CLOCK = "vc.clock";
public const string MMAL_COMPONENT_DEFAULT_CAMERA_INFO = "vc.camera_info";

// @waveform80 The following two components aren't in the MMAL headers, but do exist
// @waveform80 The following components aren't in the MMAL headers, but do exist
public const string MMAL_COMPONENT_DEFAULT_NULL_SINK = "vc.null_sink";
public const string MMAL_COMPONENT_DEFAULT_RESIZER = "vc.ril.resize";

public const string MMAL_COMPONENT_ISP = "vc.ril.isp";
public const string MMAL_COMPONENT_RAWCAM = "vc.ril.rawcam";
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
60 changes: 60 additions & 0 deletions src/MMALSharp/Ports/MMALRawcamPortConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// <copyright file="MMALRawcamPortConfig.cs" company="Techyian">
// Copyright (c) Ian Auty. All rights reserved.
// Licensed under the MIT License. Please see LICENSE.txt for License info.
// </copyright>

using MMALSharp.Native;
using System;

namespace MMALSharp.Ports
{
/// <summary>
/// Represents a port configuration object for use with the Rawcam component.
/// </summary>
public class MMALRawcamPortConfig : MMALPortConfig
{
/// <summary>
/// The physical camera interface type.
/// </summary>
public MMAL_CAMERA_INTERFACE_T CameraInterface { get; set; }

/// <summary>
/// Camera peripheral clocking mode.
/// </summary>
public MMAL_CAMERA_CLOCKING_MODE_T ClockingMode { get; set; }

/// <summary>
/// The receiver peripheral configuration for unpacking/packing DPCM, and decoding or encoding Bayer images.
/// </summary>
public MMALRawcamRxConfig RxConfig { get; set; }

/// <summary>
/// Camera peripheral timing registers.
/// </summary>
public MMALRawcamTimingConfig TimingConfig { get; set; }

/// <summary>
/// Create a new instance of <see cref="MMALRawcamPortConfig"/>.
/// </summary>
/// <param name="encodingType">The encoding type. Set this to specify the output format. Colour format should be
/// RGB565, RGB888, ABGR8888, YUV420 packed planar, YUV422 packed
/// planar, or one of the flavours of YUYV.</param>
/// <param name="pixelFormat">The pixel format.</param>
/// <param name="bitrate">The output bitrate.</param>
/// <param name="timeout">Video record timeout.</param>
/// <param name="cameraInterface">The physical camera interface type.</param>
/// <param name="clockingMode">Camera peripheral clocking mode.</param>
/// <param name="rxConfig">The receiver peripheral configuration for unpacking/packing DPCM, and decoding or encoding Bayer images.</param>
/// <param name="timingConfig">Camera peripheral timing registers.</param>
public MMALRawcamPortConfig(MMALEncoding encodingType, MMALEncoding pixelFormat, int bitrate, DateTime? timeout,
MMAL_CAMERA_INTERFACE_T cameraInterface, MMAL_CAMERA_CLOCKING_MODE_T clockingMode, MMALRawcamRxConfig rxConfig,
MMALRawcamTimingConfig timingConfig)
: base(encodingType, pixelFormat, 0, bitrate, timeout, null, false)
{
this.CameraInterface = cameraInterface;
this.ClockingMode = clockingMode;
this.RxConfig = rxConfig;
this.TimingConfig = timingConfig;
}
}
}
85 changes: 85 additions & 0 deletions src/MMALSharp/Ports/MMALRawcamRxConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// <copyright file="MMALRawcamRxConfig.cs" company="Techyian">
// Copyright (c) Ian Auty. All rights reserved.
// Licensed under the MIT License. Please see LICENSE.txt for License info.
// </copyright>

using MMALSharp.Native;

namespace MMALSharp.Ports
{
/// <summary>
/// The receiver peripheral configuration for unpacking/packing DPCM, and decoding or encoding Bayer images.
/// </summary>
public class MMALRawcamRxConfig
{
/// <summary>
/// Bayer decoding value.
/// </summary>
public MMAL_CAMERA_RX_CONFIG_DECODE DecodeConfig { get; set; }

/// <summary>
/// Bayer encoding value.
/// </summary>
public MMAL_CAMERA_RX_CONFIG_ENCODE EncodeConfig { get; set; }

/// <summary>
/// DPCM unpacking value.
/// </summary>
public MMAL_CAMERA_RX_CONFIG_UNPACK UnpackConfig { get; set; }

/// <summary>
/// DPCM packing value.
/// </summary>
public MMAL_CAMERA_RX_CONFIG_PACK PackConfig { get; set; }

/// <summary>
/// Unsure.
/// </summary>
public int DataLanes { get; set; }

/// <summary>
/// Unsure.
/// </summary>
public int EncodeBlockLength { get; set; }

/// <summary>
/// Unsure.
/// </summary>
public int EmbeddedDataLines { get; set; }

/// <summary>
/// Unsure.
/// </summary>
public int ImageId { get; set; }

/// <summary>
/// Creates a new instance of <see cref="MMALRawcamRxConfig"/> for use with the Rawcam component port configuration.
/// </summary>
/// <param name="decodeConfig">Bayer decoding value.</param>
/// <param name="encodeConfig">Bayer encoding value.</param>
/// <param name="unpackConfig">DPCM unpacking value.</param>
/// <param name="packConfig">DPCM packing value.</param>
/// <param name="dataLanes">Data lanes value - unsure.</param>
/// <param name="encodeBlockLength">Encode block length value - Unsure.</param>
/// <param name="embeddedDataLanes">Embedded data lanes value - Unsure.</param>
/// <param name="imageId">Image ID value - Unsure.</param>
public MMALRawcamRxConfig(MMAL_CAMERA_RX_CONFIG_DECODE decodeConfig,
MMAL_CAMERA_RX_CONFIG_ENCODE encodeConfig,
MMAL_CAMERA_RX_CONFIG_UNPACK unpackConfig,
MMAL_CAMERA_RX_CONFIG_PACK packConfig,
int dataLanes,
int encodeBlockLength,
int embeddedDataLanes,
int imageId)
{
this.DecodeConfig = decodeConfig;
this.EncodeConfig = encodeConfig;
this.UnpackConfig = unpackConfig;
this.PackConfig = packConfig;
this.DataLanes = dataLanes;
this.EncodeBlockLength = encodeBlockLength;
this.EmbeddedDataLines = embeddedDataLanes;
this.ImageId = imageId;
}
}
}
Loading

1 comment on commit 610ba75

@techyian
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracked against #124.

Please sign in to comment.