├── tests └── MMALSharp.Tests │ ├── xunit.runner.json │ ├── TestMember.cs │ ├── Data │ ├── BasicImageData.cs │ ├── RawImageData.cs │ ├── CustomConnectionCallbackHandler.cs │ ├── ImageData.cs │ ├── VideoData.cs │ └── ImageFxData.cs │ ├── DisplayTestMethodNameAttribute.cs │ ├── NLog.config │ ├── MMALSharp.Tests.csproj │ ├── MMALFixture.cs │ ├── TestHelper.cs │ ├── ColorConversionTests.cs │ └── FFmpegTests.cs ├── src ├── MMALSharp │ ├── App.config │ ├── Callbacks │ │ ├── ICallbackHandler.cs │ │ ├── IVideoOutputCallbackHandler.cs │ │ ├── IOutputCallbackHandler.cs │ │ ├── DefaultConnectionCallbackHandler.cs │ │ ├── IInputCallbackHandler.cs │ │ ├── DefaultPortCallbackHandler.cs │ │ ├── DefaultInputPortCallbackHandler.cs │ │ ├── DefaultOutputPortCallbackHandler.cs │ │ ├── IConnectionCallbackHandler.cs │ │ ├── FastImageOutputCallbackHandler.cs │ │ ├── ConnectionCallbackHandler.cs │ │ └── InputPortCallbackHandler.cs │ ├── Ports │ │ ├── Outputs │ │ │ ├── IStillPort.cs │ │ │ ├── IVideoPort.cs │ │ │ ├── SplitterStillPort.cs │ │ │ ├── SplitterOutputPort.cs │ │ │ ├── SplitterVideoPort.cs │ │ │ ├── IOutputPort.cs │ │ │ └── StillPort.cs │ │ ├── Controls │ │ │ └── IControlPort.cs │ │ ├── PortType.cs │ │ ├── Clocks │ │ │ └── ClockPort.cs │ │ ├── Inputs │ │ │ ├── OverlayPort.cs │ │ │ └── IInputPort.cs │ │ ├── GenericPort.cs │ │ └── IMMALPortConfig.cs │ ├── Components │ │ ├── EncoderComponents │ │ │ ├── IEncoder.cs │ │ │ ├── IImageDecoder.cs │ │ │ ├── IVideoDecoder.cs │ │ │ ├── IVideoEncoder.cs │ │ │ ├── IMMALConvert.cs │ │ │ ├── MMALEncoderBase.cs │ │ │ ├── IImageEncoder.cs │ │ │ ├── MMALVideoDecoder.cs │ │ │ └── MMALImageDecoder.cs │ │ ├── IDownstreamHandlerComponent.cs │ │ ├── ICameraInfoComponent.cs │ │ ├── MMALDownstreamHandlerComponent.cs │ │ ├── MMALResizerComponent.cs │ │ ├── ICameraComponent.cs │ │ ├── MMALSplitterComponent.cs │ │ └── MMALIspComponent.cs │ ├── Config │ │ ├── ExifTag.cs │ │ ├── Split.cs │ │ ├── TimelapseMode.cs │ │ ├── Timelapse.cs │ │ ├── ColourEffects.cs │ │ ├── PreviewOverlayConfiguration.cs │ │ ├── StereoMode.cs │ │ ├── Zoom.cs │ │ ├── JpegThumbnail.cs │ │ └── PreviewConfiguration.cs │ ├── Parameter.cs │ ├── MMALBootstrapper.cs │ ├── IMMALObject.cs │ ├── MMALObject.cs │ ├── Native │ │ ├── BcmHost.cs │ │ ├── MMALCommon.cs │ │ ├── MMALQueue.cs │ │ ├── MMALEvents.cs │ │ └── MMALPool.cs │ ├── IBufferPool.cs │ ├── IBufferQueue.cs │ ├── MMALSharp.csproj │ ├── IBufferEvent.cs │ └── MMALPoolImpl.cs ├── MMALSharp.Common │ ├── Enumerations.cs │ ├── BufferMetadata.cs │ ├── Utility │ │ ├── CancellationTokenExtensions.cs │ │ ├── Helpers.cs │ │ └── Logging.cs │ ├── MMALSharp.Common.csproj │ ├── ImageContext.cs │ └── GenericExtensions.cs ├── MMALSharp.Processing │ ├── Processors │ │ ├── Bayer │ │ │ ├── DemosaicProcessor.cs │ │ │ ├── BayerOperationsExtensions.cs │ │ │ └── BayerMetaProcessor.cs │ │ ├── Motion │ │ │ ├── MotionType.cs │ │ │ ├── MotionVectorAnalyser.cs │ │ │ ├── MotionConfig.cs │ │ │ └── IMotionAlgorithm.cs │ │ ├── IFrameAnalyser.cs │ │ ├── IFrameProcessor.cs │ │ ├── IFrameProcessingContext.cs │ │ ├── FrameProcessingContext.cs │ │ ├── Effects │ │ │ ├── BoxBlur.cs │ │ │ ├── SharpenProcessor.cs │ │ │ ├── CustomConvolutionProcessor.cs │ │ │ ├── EdgeDetection.cs │ │ │ └── GaussianProcessor.cs │ │ └── FrameAnalysisMetadata.cs │ ├── Handlers │ │ ├── IVideoCaptureHandler.cs │ │ ├── ICaptureHandler.cs │ │ ├── IInputCaptureHandler.cs │ │ ├── IOutputCaptureHandler.cs │ │ ├── IMotionVectorCaptureHandler.cs │ │ ├── IFileStreamCaptureHandler.cs │ │ ├── MemoryStreamCaptureHandler.cs │ │ ├── ImageStreamCaptureHandler.cs │ │ ├── ProcessResult.cs │ │ ├── ProcessedFileResult.cs │ │ ├── IMotionCaptureHandler.cs │ │ ├── InMemoryCaptureHandler.cs │ │ ├── InputCaptureHandler.cs │ │ ├── OutputCaptureHandler.cs │ │ ├── StreamCaptureHandler.cs │ │ └── ExternalProcessCaptureHandlerOptions.cs │ └── MMALSharp.Processing.csproj ├── MMALSharp.Demo │ ├── MMALSharp.Demo.csproj │ ├── OpsBase.cs │ ├── Program.cs │ └── VideoOps.cs └── MMALSharp.FFmpeg │ ├── MMALSharp.FFmpeg.csproj │ └── VideoUtilities.cs ├── NuGet.config ├── LICENSE.txt ├── run-sonar.ps1 └── .gitattributes /tests/MMALSharp.Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "parallelizeTestCollections": false, 3 | "shadowCopy": false, 4 | "maxParallelThreads": -1 5 | } -------------------------------------------------------------------------------- /src/MMALSharp/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/Enumerations.cs: -------------------------------------------------------------------------------- 1 | namespace MMALSharp.Common 2 | { 3 | /// 4 | /// Represents a Raspberry Pi camera module model. 5 | /// 6 | public enum CameraVersion 7 | { 8 | /// 9 | /// SUNNY OV5647. 10 | /// 11 | OV5647, 12 | 13 | /// 14 | /// Sony IMX219. 15 | /// 16 | IMX219 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/ICallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Callbacks 7 | { 8 | /// 9 | /// Represents a callback handler. 10 | /// 11 | public interface ICallbackHandler 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/IStillPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Ports.Outputs 7 | { 8 | /// 9 | /// Represents a still port. 10 | /// 11 | public interface IStillPort : IOutputPort 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/IVideoPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Ports.Outputs 7 | { 8 | /// 9 | /// Represents a video port. 10 | /// 11 | public interface IVideoPort : IOutputPort 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components.EncoderComponents 7 | { 8 | /// 9 | /// Represents an encoder component. 10 | /// 11 | public interface IEncoder : IDownstreamHandlerComponent 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IImageDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components.EncoderComponents 7 | { 8 | /// 9 | /// Represents a image decoder component. 10 | /// 11 | public interface IImageDecoder : IEncoder 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IVideoDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components.EncoderComponents 7 | { 8 | /// 9 | /// Represents a video decoder component. 10 | /// 11 | public interface IVideoDecoder : IEncoder 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IVideoEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components.EncoderComponents 7 | { 8 | /// 9 | /// Represents a video encoder component. 10 | /// 11 | public interface IVideoEncoder : IEncoder 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/IVideoOutputCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Callbacks 7 | { 8 | /// 9 | /// Represents a video output port callback handler. 10 | /// 11 | public interface IVideoOutputCallbackHandler 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Bayer/DemosaicProcessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MMALSharp.Common; 3 | 4 | namespace MMALSharp.Processors.Bayer 5 | { 6 | /// 7 | /// The DemosaicProcessor is used to apply a demosaic algorithm to Bayer metadata. 8 | /// 9 | public class DemosaicProcessor : IFrameProcessor 10 | { 11 | /// 12 | public void Apply(ImageContext context) 13 | { 14 | throw new NotImplementedException(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/IDownstreamHandlerComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components 7 | { 8 | /// 9 | /// Represents a downstream handler component. 10 | /// 11 | public interface IDownstreamHandlerComponent : IDownstreamComponent 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MMALSharp.Demo/MMALSharp.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Controls/IControlPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Ports.Controls 7 | { 8 | /// 9 | /// Represents a control port. 10 | /// 11 | public interface IControlPort : IPort 12 | { 13 | /// 14 | /// Starts the control port. 15 | /// 16 | void Start(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/TestMember.cs: -------------------------------------------------------------------------------- 1 | using MMALSharp.Common; 2 | using MMALSharp.Native; 3 | 4 | namespace MMALSharp.Tests 5 | { 6 | public class TestMember 7 | { 8 | public string Extension { get; set; } 9 | public MMALEncoding EncodingType { get; set; } 10 | public MMALEncoding PixelFormat { get; set; } 11 | 12 | public TestMember(string extension, MMALEncoding encodingType, MMALEncoding pixelFormat) 13 | { 14 | this.Extension = extension; 15 | this.EncodingType = encodingType; 16 | this.PixelFormat = pixelFormat; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IVideoCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Handlers 7 | { 8 | /// 9 | /// Represents a VideoCaptureHandler for use when recording video frames. 10 | /// 11 | public interface IVideoCaptureHandler : IOutputCaptureHandler 12 | { 13 | /// 14 | /// Signals that we should begin writing to a new video file. 15 | /// 16 | void Split(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Motion/MotionType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Processors.Motion 7 | { 8 | /// 9 | /// Describes motion detection type to use. 10 | /// 11 | public enum MotionType 12 | { 13 | /// 14 | /// Frame difference. 15 | /// 16 | FrameDiff, 17 | 18 | /// 19 | /// Motion vector comparison. 20 | /// 21 | MotionVector 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/BasicImageData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace MMALSharp.Tests 9 | { 10 | public class BasicImageData 11 | { 12 | public static IEnumerable Data 13 | { 14 | get 15 | { 16 | var list = new List(); 17 | 18 | list.AddRange(TestBase.JpegEncoderData); 19 | 20 | return list; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/MMALSharp/Config/ExifTag.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Config 7 | { 8 | /// 9 | /// Represents an Exif tag for use with JPEG still captures. 10 | /// 11 | public class ExifTag 12 | { 13 | /// 14 | /// The Exif key. 15 | /// 16 | public string Key { get; set; } 17 | 18 | /// 19 | /// The Exif value. 20 | /// 21 | public string Value { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IMMALConvert.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components 7 | { 8 | /// 9 | /// Supports converting user provided image data. 10 | /// 11 | public interface IMMALConvert 12 | { 13 | /// 14 | /// Encodes/decodes user provided image data. 15 | /// 16 | /// The output port to begin processing on. 17 | void Convert(int outputPort); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/IFrameAnalyser.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | 8 | namespace MMALSharp.Processors 9 | { 10 | /// 11 | /// Represents a frame analyser. 12 | /// 13 | public interface IFrameAnalyser 14 | { 15 | /// 16 | /// The operation to perform analysis. 17 | /// 18 | /// Contains the data and metadata for an image frame. 19 | void Apply(ImageContext context); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/IFrameProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | 8 | namespace MMALSharp.Processors 9 | { 10 | /// 11 | /// A processor to apply image processing techniques on image frame data. 12 | /// 13 | public interface IFrameProcessor 14 | { 15 | /// 16 | /// Apply the convolution. 17 | /// 18 | /// The image's metadata. 19 | void Apply(ImageContext context); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MMALSharp/Parameter.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | 8 | namespace MMALSharp 9 | { 10 | internal class Parameter 11 | { 12 | public Parameter(int paramVal, Type paramType, string paramName) 13 | { 14 | this.ParamValue = paramVal; 15 | this.ParamType = paramType; 16 | this.ParamName = paramName; 17 | } 18 | 19 | public int ParamValue { get; set; } 20 | 21 | public Type ParamType { get; set; } 22 | 23 | public string ParamName { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/IOutputCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Callbacks 7 | { 8 | /// 9 | /// Represents an output port callback handler. 10 | /// 11 | public interface IOutputCallbackHandler : ICallbackHandler 12 | { 13 | /// 14 | /// The callback function to carry out. Applies to output, control and connection ports. 15 | /// 16 | /// The working buffer header. 17 | void Callback(IBuffer buffer); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/BufferMetadata.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Common 7 | { 8 | /// 9 | /// This class contains metadata for a MMAL Buffer header. 10 | /// 11 | public class BufferMetadata 12 | { 13 | /// 14 | /// The buffer represents the end of stream. 15 | /// 16 | public bool Eos { get; set; } 17 | 18 | /// 19 | /// The buffer contains IFrame data. 20 | /// 21 | public bool IFrame { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/RawImageData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace MMALSharp.Tests 9 | { 10 | public class RawImageData 11 | { 12 | public static IEnumerable Data 13 | { 14 | get 15 | { 16 | yield return TestBase.Yuv420EncoderData; 17 | yield return TestBase.Rgb16EncoderData; 18 | yield return TestBase.Rgb24EncoderData; 19 | yield return TestBase.RgbaEncoderData; 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/ICaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Provides the functionality to process user provided or captured image data. 12 | /// 13 | public interface ICaptureHandler : IDisposable 14 | { 15 | /// 16 | /// Returns a string of how much data has been processed by this capture handler. 17 | /// 18 | /// How much data has been processed by this capture handler. 19 | string TotalProcessed(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/MMALSharp/MMALBootstrapper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | using MMALSharp.Components; 8 | 9 | namespace MMALSharp 10 | { 11 | /// 12 | /// Used as a common class to store downstream component references between standalone mode and camera connected mode. 13 | /// 14 | public static class MMALBootstrapper 15 | { 16 | /// 17 | /// List of all encoders currently in the pipeline. 18 | /// 19 | public static List DownstreamComponents { get; } = new List(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IInputCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Handlers 7 | { 8 | /// 9 | /// Represents a capture handler attached to an Input port. 10 | /// 11 | public interface IInputCaptureHandler : ICaptureHandler 12 | { 13 | /// 14 | /// Processes image data to an input port. 15 | /// 16 | /// The feed chunk size. 17 | /// A with the fed image data. 18 | ProcessResult Process(uint allocSize); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/Split.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Config 7 | { 8 | /// 9 | /// The type is used when taking video capture and a user wishes to split 10 | /// recording into multiple files. 11 | /// 12 | public class Split 13 | { 14 | /// 15 | /// How often files should be split. 16 | /// 17 | public int Value { get; set; } 18 | 19 | /// 20 | /// The mode to use. 21 | /// 22 | public TimelapseMode Mode { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/MMALSharp/IMMALObject.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | 8 | namespace MMALSharp 9 | { 10 | /// 11 | /// Represents a MMAL object. 12 | /// 13 | public interface IMMALObject : IDisposable 14 | { 15 | /// 16 | /// Checks whether a native MMAL pointer is valid. 17 | /// 18 | /// True if the pointer is valid. 19 | bool CheckState(); 20 | 21 | /// 22 | /// Returns whether this MMAL object has been disposed of. 23 | /// 24 | bool IsDisposed { get; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/IFrameProcessingContext.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Processors 7 | { 8 | /// 9 | /// A context to apply image processing techniques on image frames. 10 | /// 11 | public interface IFrameProcessingContext 12 | { 13 | /// 14 | /// Applies a processing function on an image frame. 15 | /// 16 | /// The image processor. 17 | /// The active image context. 18 | IFrameProcessingContext Apply(IFrameProcessor processor); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/DefaultConnectionCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Callbacks 7 | { 8 | /// 9 | /// Default callback handler for connections. 10 | /// 11 | public class DefaultConnectionCallbackHandler : ConnectionCallbackHandler 12 | { 13 | /// 14 | /// Create a new instance of . 15 | /// 16 | /// The connection object. 17 | public DefaultConnectionCallbackHandler(IConnection connection) 18 | : base(connection) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/ICameraInfoComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components 7 | { 8 | /// 9 | /// Represents a camera info component. 10 | /// 11 | public interface ICameraInfoComponent : IComponent 12 | { 13 | /// 14 | /// The camera sensor name. 15 | /// 16 | string SensorName { get; } 17 | 18 | /// 19 | /// The camera's max operating width. 20 | /// 21 | int MaxWidth { get; } 22 | 23 | /// 24 | /// The camera's max operating height. 25 | /// 26 | int MaxHeight { get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/TimelapseMode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Config 7 | { 8 | /// 9 | /// The unit of time to use. 10 | /// 11 | public enum TimelapseMode 12 | { 13 | /// 14 | /// Uses milliseconds as unit of time. One hour equals 3'600'000 milliseconds. 15 | /// 16 | Millisecond, 17 | 18 | /// 19 | /// Uses seconds as unit of time. One hour equals 3'600 seconds. 20 | /// 21 | Second, 22 | 23 | /// 24 | /// Uses minutes as unit of time. One hour equals 60 minutes. 25 | /// 26 | Minute 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/IInputCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | 8 | namespace MMALSharp.Callbacks 9 | { 10 | /// 11 | /// Represents a callback handler linked to an Input port. 12 | /// 13 | public interface IInputCallbackHandler : ICallbackHandler 14 | { 15 | /// 16 | /// The callback function to carry out. Applies to input ports. 17 | /// 18 | /// The working buffer header. 19 | /// A object based on the result of the callback function. 20 | ProcessResult CallbackWithResult(IBuffer buffer); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/MMALEncoderBase.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Components.EncoderComponents; 7 | 8 | namespace MMALSharp.Components 9 | { 10 | /// 11 | /// Represents a base class for all encoder components. 12 | /// 13 | public abstract class MMALEncoderBase : MMALDownstreamHandlerComponent, IEncoder 14 | { 15 | /// 16 | /// Creates a new instance of . 17 | /// 18 | /// The name of the encoder component. 19 | protected MMALEncoderBase(string encoderName) 20 | : base(encoderName) 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/CustomConnectionCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using Microsoft.Extensions.Logging; 7 | using MMALSharp.Callbacks; 8 | using MMALSharp.Common.Utility; 9 | 10 | namespace MMALSharp.Tests.Data 11 | { 12 | public class CustomConnectionCallbackHandler : ConnectionCallbackHandler 13 | { 14 | public CustomConnectionCallbackHandler(IConnection connection) 15 | : base(connection) 16 | { 17 | } 18 | 19 | public override void InputCallback(IBuffer buffer) 20 | { 21 | base.InputCallback(buffer); 22 | 23 | MMALLog.Logger.LogInformation("In the custom input callback handler."); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/DisplayTestMethodNameAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Reflection; 8 | using Xunit.Sdk; 9 | 10 | namespace MMALSharp.Tests 11 | { 12 | public class MMALTestsAttribute : BeforeAfterTestAttribute 13 | { 14 | public override void Before(MethodInfo methodUnderTest) 15 | { 16 | TestHelper.SetConfigurationDefaults(); 17 | Console.WriteLine("Running test '{0}.'", methodUnderTest.Name); 18 | } 19 | 20 | public override void After(MethodInfo methodUnderTest) 21 | { 22 | TestHelper.SetConfigurationDefaults(); 23 | base.After(methodUnderTest); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/MMALDownstreamHandlerComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Components 7 | { 8 | /// 9 | /// Base class for all downstream components which support capture handlers. 10 | /// 11 | public abstract class MMALDownstreamHandlerComponent : MMALDownstreamComponent, IDownstreamHandlerComponent 12 | { 13 | /// 14 | /// Creates a new instance of . 15 | /// 16 | /// The name of the component. 17 | protected MMALDownstreamHandlerComponent(string name) 18 | : base(name) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/PortType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Ports 7 | { 8 | /// 9 | /// Describes a port type. 10 | /// 11 | public enum PortType 12 | { 13 | /// 14 | /// An input port. 15 | /// 16 | Input, 17 | 18 | /// 19 | /// An output port. 20 | /// 21 | Output, 22 | 23 | /// 24 | /// A clock port. 25 | /// 26 | Clock, 27 | 28 | /// 29 | /// A control port. 30 | /// 31 | Control, 32 | 33 | /// 34 | /// A generic port. 35 | /// 36 | Generic 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Motion/MotionVectorAnalyser.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Common; 8 | 9 | namespace MMALSharp.Processors.Motion 10 | { 11 | /// 12 | /// A frame analyser for use with motion vector detection. 13 | /// 14 | public class MotionVectorAnalyser : FrameAnalyser 15 | { 16 | internal Action OnDetect { get; set; } 17 | 18 | /// 19 | /// Creates a new instance of . 20 | /// 21 | public MotionVectorAnalyser() 22 | { 23 | } 24 | 25 | /// 26 | public override void Apply(ImageContext context) 27 | { 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IOutputCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Represents a capture handler attached to an Output port. 12 | /// 13 | public interface IOutputCaptureHandler : ICaptureHandler 14 | { 15 | /// 16 | /// Used to process the image data from an output port. 17 | /// 18 | /// Contains the data and metadata for an image frame. 19 | void Process(ImageContext context); 20 | 21 | /// 22 | /// Used for any further processing once we have completed capture. 23 | /// 24 | void PostProcess(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/DefaultPortCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Ports; 8 | 9 | namespace MMALSharp.Callbacks 10 | { 11 | /// 12 | /// A default callback handler for ports. 13 | /// 14 | public class DefaultPortCallbackHandler : PortCallbackHandler 15 | { 16 | /// 17 | /// Creates a new instance of . 18 | /// 19 | /// The working . 20 | /// The port capture handler. 21 | public DefaultPortCallbackHandler(IPort port, IOutputCaptureHandler handler) 22 | : base(port, handler) 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/Timelapse.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Threading; 7 | 8 | namespace MMALSharp.Config 9 | { 10 | /// 11 | /// The type is for use with Timelapse still captures. 12 | /// 13 | public class Timelapse 14 | { 15 | /// 16 | /// The timelapse mode. 17 | /// 18 | public TimelapseMode Mode { get; set; } 19 | 20 | /// 21 | /// Specifies when timelapse capture should finish. 22 | /// 23 | public CancellationToken CancellationToken { get; set; } 24 | 25 | /// 26 | /// How often images should be taken (relates to the chosen). 27 | /// 28 | public int Value { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Clocks/ClockPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Callbacks; 8 | using MMALSharp.Components; 9 | 10 | namespace MMALSharp.Ports.Clocks 11 | { 12 | /// 13 | /// Represents a clock port. 14 | /// 15 | public class ClockPort : GenericPort 16 | { 17 | /// 18 | /// Creates a new instance of . 19 | /// 20 | /// The native pointer. 21 | /// The component this port is associated with. 22 | /// Managed unique identifier for this component. 23 | public ClockPort(IntPtr ptr, IComponent comp, Guid guid) 24 | : base(ptr, comp, PortType.Clock, guid) 25 | { 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/DefaultInputPortCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Ports.Inputs; 8 | 9 | namespace MMALSharp.Callbacks 10 | { 11 | /// 12 | /// A default callback handler for ports. 13 | /// 14 | public class DefaultInputPortCallbackHandler : InputPortCallbackHandler 15 | { 16 | /// 17 | /// Creates a new instance of . 18 | /// 19 | /// The working . 20 | /// The input port capture handler. 21 | public DefaultInputPortCallbackHandler(IInputPort port, IInputCaptureHandler handler) 22 | : base(port, handler) 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IMotionVectorCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.IO; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Represents a capture handler which can process motion vectors. 12 | /// 13 | public interface IMotionVectorCaptureHandler 14 | { 15 | /// 16 | /// Call to initialise the stream to write motion vectors to. 17 | /// 18 | /// The stream to write to. 19 | void InitialiseMotionStore(Stream stream); 20 | 21 | /// 22 | /// Responsible for storing the motion vector data to an output stream. 23 | /// 24 | /// The byte array containing the motion vector data. 25 | void ProcessMotionVectors(byte[] data); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/DefaultOutputPortCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Ports.Outputs; 8 | 9 | namespace MMALSharp.Callbacks 10 | { 11 | /// 12 | /// A default callback handler for ports. 13 | /// 14 | public class DefaultOutputPortCallbackHandler : PortCallbackHandler 15 | { 16 | /// 17 | /// Creates a new instance of . 18 | /// 19 | /// The working . 20 | /// The output port capture handler. 21 | public DefaultOutputPortCallbackHandler(IOutputPort port, IOutputCaptureHandler handler) 22 | : base(port, handler) 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IFileStreamCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Handlers 7 | { 8 | /// 9 | /// Represents a FileStreamCaptureHandler. 10 | /// 11 | public interface IFileStreamCaptureHandler : IOutputCaptureHandler 12 | { 13 | /// 14 | /// Creates a new File (FileStream), assigns it to the Stream instance of this class and disposes of any existing stream. 15 | /// 16 | void NewFile(); 17 | 18 | /// 19 | /// Gets the filepath that a FileStream points to. 20 | /// 21 | /// The filepath. 22 | string GetFilepath(); 23 | 24 | /// 25 | /// Gets the filename that a FileStream points to. 26 | /// 27 | /// The filename. 28 | string GetFilename(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2020 Ian Auty and contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/IImageEncoder.cs: -------------------------------------------------------------------------------- 1 | using MMALSharp.Config; 2 | 3 | namespace MMALSharp.Components.EncoderComponents 4 | { 5 | /// 6 | /// Represents an image encoder component. 7 | /// 8 | public interface IImageEncoder : IEncoder 9 | { 10 | /// 11 | /// Flag to return raw Bayer metadata with JPEG frames. 12 | /// 13 | bool RawBayer { get; } 14 | 15 | /// 16 | /// Flag to add EXIF tags to image frames. 17 | /// 18 | bool UseExif { get; } 19 | 20 | /// 21 | /// An array of user provided EXIF tags. 22 | /// 23 | ExifTag[] ExifTags { get; } 24 | 25 | /// 26 | /// When enabled and if configured, image frames will be quickly processed by the camera's video port. 27 | /// 28 | bool ContinuousCapture { get; } 29 | 30 | /// 31 | /// The JPEG thumbnail configuration object. 32 | /// 33 | JpegThumbnail JpegThumbnailConfig { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/ImageData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace MMALSharp.Tests 9 | { 10 | public class ImageData 11 | { 12 | public static IEnumerable Data 13 | { 14 | get 15 | { 16 | var list = new List(); 17 | 18 | list.AddRange(TestBase.JpegEncoderData); 19 | list.AddRange(TestBase.GifEncoderData); 20 | list.AddRange(TestBase.PngEncoderData); 21 | list.AddRange(TestBase.BmpEncoderData); 22 | 23 | // TGA/PPM support is enabled by performing a firmware update "sudo rpi-update". 24 | // See: https://github.com/techyian/MMALSharp/issues/23 25 | 26 | // list.AddRange(TestData.TgaEncoderData); 27 | // list.AddRange(TestData.PpmEncoderData); 28 | return list; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/MMALSharp/MMALObject.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp 7 | { 8 | /// 9 | /// This class is the base class for all MMAL components. 10 | /// 11 | public abstract class MMALObject : IMMALObject 12 | { 13 | /// 14 | /// Returns whether this MMAL object has been disposed of. 15 | /// 16 | public bool IsDisposed { get; internal set; } 17 | 18 | /// 19 | /// Creates a new instance of the MMALObject class and adds this instance to the Objects list. 20 | /// 21 | protected MMALObject() 22 | { 23 | } 24 | 25 | /// 26 | /// Marks this object as disposed. 27 | /// 28 | public virtual void Dispose() 29 | { 30 | this.IsDisposed = true; 31 | } 32 | 33 | /// 34 | public abstract bool CheckState(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/FrameProcessingContext.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | 8 | namespace MMALSharp.Processors 9 | { 10 | /// 11 | /// A context providing a means to apply image processing. 12 | /// 13 | public class FrameProcessingContext : IFrameProcessingContext 14 | { 15 | private ImageContext _context; 16 | 17 | /// 18 | /// Creates a new instance of . 19 | /// 20 | /// Metadata for the image frame. 21 | public FrameProcessingContext(ImageContext context) 22 | { 23 | _context = context; 24 | } 25 | 26 | /// 27 | public IFrameProcessingContext Apply(IFrameProcessor processor) 28 | { 29 | processor.Apply(_context); 30 | 31 | return this; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/IConnectionCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Callbacks 7 | { 8 | /// 9 | /// Represents a connection callback handler. 10 | /// 11 | public interface IConnectionCallbackHandler : ICallbackHandler 12 | { 13 | /// 14 | /// The connection this callback handler is used with. 15 | /// 16 | IConnection WorkingConnection { get; } 17 | 18 | /// 19 | /// The input port callback function to carry out. 20 | /// 21 | /// The working buffer header. 22 | void InputCallback(IBuffer buffer); 23 | 24 | /// 25 | /// The output port callback function to carry out. 26 | /// 27 | /// The working buffer header. 28 | void OutputCallback(IBuffer buffer); 29 | } 30 | } -------------------------------------------------------------------------------- /src/MMALSharp/Config/ColourEffects.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Drawing; 7 | 8 | namespace MMALSharp.Config 9 | { 10 | /// 11 | /// Allows a user to adjust the colour of outputted frames. 12 | /// 13 | public struct ColourEffects 14 | { 15 | /// 16 | /// Enable the Colour Effects functionality. 17 | /// 18 | public bool Enable { get; } 19 | 20 | /// 21 | /// The to use. 22 | /// 23 | public Color Color { get; } 24 | 25 | /// 26 | /// Initialises a new struct. 27 | /// 28 | /// Enable the Colour Effects functionality. 29 | /// The to use. 30 | public ColourEffects(bool enable, Color color) 31 | { 32 | Enable = enable; 33 | Color = color; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/MemoryStreamCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.IO; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Processes frame data to a . 12 | /// 13 | public class MemoryStreamCaptureHandler : StreamCaptureHandler 14 | { 15 | /// 16 | /// Creates a new instance of . 17 | /// 18 | public MemoryStreamCaptureHandler() 19 | { 20 | this.CurrentStream = new MemoryStream(); 21 | } 22 | 23 | /// 24 | /// Creates a new instance of with a specified capacity. 25 | /// 26 | /// The capacity of the . 27 | public MemoryStreamCaptureHandler(int size) 28 | { 29 | this.CurrentStream = new MemoryStream(size); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/Utility/CancellationTokenExtensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace MMALSharp.Common.Utility 10 | { 11 | /// 12 | /// This class provides extensions for s. 13 | /// 14 | public static class CancellationTokenExtensions 15 | { 16 | /// 17 | /// Returns a whose state will be set to when this is canceled. 18 | /// 19 | /// The cancellation token. 20 | /// The task. 21 | public static Task AsTask(this CancellationToken cancellationToken) 22 | { 23 | var tcs = new TaskCompletionSource(); 24 | cancellationToken.Register(() => { tcs.TrySetCanceled(); }, useSynchronizationContext: false); 25 | return tcs.Task; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/PreviewOverlayConfiguration.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using MMALSharp.Common.Utility; 8 | using MMALSharp.Components; 9 | 10 | namespace MMALSharp.Config 11 | { 12 | /// 13 | /// Defines the settings for a component. 14 | /// 15 | public class PreviewOverlayConfiguration : PreviewConfiguration 16 | { 17 | /// 18 | /// Specifies the resolution of the static resource to be used with this Preview Overlay. If this is null then the parent renderer's resolution will be used instead. 19 | /// 20 | public Resolution Resolution { get; set; } 21 | 22 | /// 23 | /// The encoding of the static resource. Can be one of the following: YUV, RGB, RGBA, BGR, BGRA. 24 | /// If left null, we will try to work out the encoding based on the size of the image (3 bytes for RGB, 4 bytes for RGBA). 25 | /// 26 | public MMALEncoding Encoding { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/MMALSharp/Native/BcmHost.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Runtime.InteropServices; 7 | 8 | namespace MMALSharp.Native 9 | { 10 | /// 11 | /// Provides interop methods for libbcm_host, the Broadcom hardware interface library. 12 | /// 13 | public static class BcmHost 14 | { 15 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 16 | #pragma warning disable IDE1006 // Naming Styles 17 | 18 | [DllImport("libbcm_host.so", EntryPoint = "bcm_host_init", CallingConvention = CallingConvention.Cdecl)] 19 | public static extern void bcm_host_init(); 20 | 21 | [DllImport("libbcm_host.so", EntryPoint = "bcm_host_deinit", CallingConvention = CallingConvention.Cdecl)] 22 | public static extern void bcm_host_deinit(); 23 | 24 | [DllImport("libbcm_host.so", EntryPoint = "graphics_get_display_size", CallingConvention = CallingConvention.Cdecl)] 25 | public static extern unsafe int graphics_get_display_size(ushort display_number, uint* width, uint* height); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/VideoData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | 8 | namespace MMALSharp.Tests 9 | { 10 | public class VideoData 11 | { 12 | public static IEnumerable H264Data 13 | { 14 | get 15 | { 16 | var list = new List(); 17 | 18 | list.AddRange(TestBase.H264EncoderData); 19 | 20 | return list; 21 | } 22 | } 23 | 24 | public static IEnumerable MJPEGData 25 | { 26 | get 27 | { 28 | var list = new List(); 29 | 30 | list.AddRange(TestBase.MjpegEncoderData); 31 | 32 | return list; 33 | } 34 | } 35 | 36 | public static IEnumerable Data 37 | { 38 | get 39 | { 40 | var list = new List(); 41 | 42 | list.AddRange(TestBase.H264EncoderData); 43 | list.AddRange(TestBase.MjpegEncoderData); 44 | 45 | return list; 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/MMALVideoDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Components.EncoderComponents; 8 | using MMALSharp.Native; 9 | using MMALSharp.Ports.Inputs; 10 | using MMALSharp.Ports.Outputs; 11 | 12 | namespace MMALSharp.Components 13 | { 14 | /// 15 | /// This conformant component accepts encoded video in a number of 16 | /// different formats, and decodes it to raw YUV frames. 17 | /// https://github.com/raspberrypi/firmware/blob/master/documentation/ilcomponents/video_decode.html 18 | /// 19 | public class MMALVideoDecoder : MMALEncoderBase, IVideoDecoder 20 | { 21 | /// 22 | /// Creates a new instance of . 23 | /// 24 | public unsafe MMALVideoDecoder() 25 | : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_DECODER) 26 | { 27 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 28 | this.Outputs.Add(new VideoPort((IntPtr)(&(*this.Ptr->Output[0])), this, Guid.NewGuid())); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MMALSharp.Demo/OpsBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MMALSharp.Common; 3 | using MMALSharp.Native; 4 | 5 | namespace MMALSharp.Demo 6 | { 7 | public abstract class OpsBase 8 | { 9 | protected MMALCamera Cam => MMALCamera.Instance; 10 | 11 | public abstract void Operations(); 12 | 13 | protected Tuple ParsePixelFormat() 14 | { 15 | Console.WriteLine("\nPlease select an image format."); 16 | var format = Console.ReadLine(); 17 | Console.WriteLine("\nPlease select a pixel format."); 18 | var pixelFormat = Console.ReadLine(); 19 | 20 | if (string.IsNullOrEmpty(format) || string.IsNullOrEmpty(pixelFormat)) 21 | { 22 | Console.WriteLine("Please enter valid formats."); 23 | this.ParsePixelFormat(); 24 | } 25 | 26 | var parsedFormat = format.ParseEncoding(); 27 | var parsedPixelFormat = format.ParseEncoding(); 28 | 29 | if (parsedFormat == null || parsedPixelFormat == null) 30 | { 31 | Console.WriteLine("Could not parse format. Please try again."); 32 | this.ParsePixelFormat(); 33 | } 34 | 35 | return new Tuple(parsedFormat, parsedPixelFormat); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/MMALSharp/IBufferPool.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Native; 7 | 8 | namespace MMALSharp 9 | { 10 | /// 11 | /// Represents a pool of buffer headers. 12 | /// 13 | public interface IBufferPool : IMMALObject 14 | { 15 | /// 16 | /// Native pointer that represents this buffer header pool. 17 | /// 18 | unsafe MMAL_POOL_T* Ptr { get; } 19 | 20 | /// 21 | /// Accessor to the queue of buffer headers this pool has. 22 | /// 23 | IBufferQueue Queue { get; } 24 | 25 | /// 26 | /// The number of buffer headers in this pool. 27 | /// 28 | uint HeadersNum { get; } 29 | 30 | /// 31 | /// Resize a pool of MMAL_BUFFER_HEADER_T. This allows modifying either the number of allocated buffers, the payload size or both at the same time. 32 | /// 33 | /// Number of headers to be contained in this pool. 34 | /// The size of the headers. 35 | void Resize(uint numHeaders, uint size); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/Utility/Helpers.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Common.Utility 7 | { 8 | /// 9 | /// Provides general helper methods. 10 | /// 11 | public class Helpers 12 | { 13 | /// 14 | /// Converts the count of bytes to megabytes in the format "0.00mb". 15 | /// 16 | /// The number of bytes. 17 | /// A string representing the byte-megabyte conversion. 18 | public static string ConvertBytesToMegabytes(long bytes) 19 | { 20 | return ((bytes / 1024f) / 1024f).ToString("0.00mb"); 21 | } 22 | 23 | /// 24 | /// Returns an integer FourCC code from a string. 25 | /// 26 | /// The FourCC code. 27 | /// The FourCC code as an integer. 28 | public static int FourCCFromString(string s) 29 | { 30 | int a1 = s[0]; 31 | int b1 = s[1]; 32 | int c1 = s[2]; 33 | int d1 = s[3]; 34 | return a1 | (b1 << 8) | (c1 << 16) | (d1 << 24); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/MMALResizerComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Ports.Inputs; 8 | using MMALSharp.Ports.Outputs; 9 | using static MMALSharp.Native.MMALParameters; 10 | 11 | namespace MMALSharp.Components 12 | { 13 | /// 14 | /// Represents the resizer component. This component has the ability to change the encoding type & pixel format, as well 15 | /// as the width/height of resulting frames. 16 | /// 17 | public sealed class MMALResizerComponent : MMALDownstreamHandlerComponent 18 | { 19 | /// 20 | /// Creates a new instance of the class that can be used to change the size 21 | /// and the pixel format of resulting frames. 22 | /// 23 | public unsafe MMALResizerComponent() 24 | : base(MMAL_COMPONENT_DEFAULT_RESIZER) 25 | { 26 | // Default to use still image port behaviour. 27 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 28 | this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[0])), this, Guid.NewGuid())); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/ImageStreamCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.IO; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Processes Image data to a . 12 | /// 13 | public class ImageStreamCaptureHandler : FileStreamCaptureHandler 14 | { 15 | /// 16 | /// Creates a new instance of the class with the specified directory and filename extension. 17 | /// 18 | /// The directory to save captured images. 19 | /// The filename extension for saving files. 20 | public ImageStreamCaptureHandler(string directory, string extension) 21 | : base(directory, extension) { } 22 | 23 | /// 24 | /// Creates a new instance of the class with the specified file path. 25 | /// 26 | /// The absolute full path to save captured data to. 27 | public ImageStreamCaptureHandler(string fullPath) 28 | : base(fullPath) { } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Effects/BoxBlur.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using System; 8 | using System.Diagnostics; 9 | 10 | namespace MMALSharp.Processors.Effects 11 | { 12 | /// 13 | /// An image processor used to apply a box-blur effect. 14 | /// 15 | public class BoxBlur : ConvolutionBase, IFrameProcessor 16 | { 17 | private const int _kernelWidth = 3; 18 | private const int _kernelHeight = 3; 19 | private double[,] _kernel = new double[3, 3] 20 | { 21 | {0.11111111, 0.11111111, 0.11111111 }, 22 | {0.11111111, 0.11111111, 0.11111111 }, 23 | {0.11111111, 0.11111111, 0.11111111 }, 24 | }; 25 | 26 | /// 27 | public BoxBlur() 28 | : base() 29 | { } 30 | 31 | /// 32 | public BoxBlur(int horizontalCellCount, int verticalCellCount) 33 | : base(horizontalCellCount, verticalCellCount) 34 | { } 35 | 36 | /// 37 | public void Apply(ImageContext context) 38 | { 39 | this.ApplyConvolution(_kernel, _kernelWidth, _kernelHeight, context); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Effects/SharpenProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using System; 8 | using System.Diagnostics; 9 | 10 | namespace MMALSharp.Processors.Effects 11 | { 12 | /// 13 | /// A image processor used to apply a sharpen effect. 14 | /// 15 | public class SharpenProcessor : ConvolutionBase, IFrameProcessor 16 | { 17 | private const int KernelWidth = 3; 18 | private const int KernelHeight = 3; 19 | 20 | private double[,] _kernel = new double[KernelWidth, KernelHeight] 21 | { 22 | { 0, -1, 0 }, 23 | { -1, 5, -1 }, 24 | { 0, -1, 0 }, 25 | }; 26 | 27 | /// 28 | public SharpenProcessor() 29 | : base() 30 | { } 31 | 32 | /// 33 | public SharpenProcessor(int horizontalCellCount, int verticalCellCount) 34 | : base(horizontalCellCount, verticalCellCount) 35 | { } 36 | 37 | /// 38 | public void Apply(ImageContext context) 39 | { 40 | this.ApplyConvolution(_kernel, KernelWidth, KernelHeight, context); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/EncoderComponents/MMALImageDecoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Components.EncoderComponents; 8 | using MMALSharp.Native; 9 | using MMALSharp.Ports.Inputs; 10 | using MMALSharp.Ports.Outputs; 11 | 12 | namespace MMALSharp.Components 13 | { 14 | /// 15 | /// A conformant image decode component, which takes encoded still images 16 | /// in various compressed formats on its input port, and decodes the image 17 | /// into raw pixels which are emitted on the output port. 18 | /// https://github.com/raspberrypi/firmware/blob/master/documentation/ilcomponents/image_decode.html 19 | /// 20 | public class MMALImageDecoder : MMALEncoderBase, IImageDecoder 21 | { 22 | /// 23 | /// Creates a new instance of . 24 | /// 25 | public unsafe MMALImageDecoder() 26 | : base(MMALParameters.MMAL_COMPONENT_DEFAULT_IMAGE_DECODER) 27 | { 28 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 29 | this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[0])), this, Guid.NewGuid())); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Bayer/BayerOperationsExtensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using MMALSharp.Processors.Bayer; 8 | 9 | namespace MMALSharp.Processors 10 | { 11 | /// 12 | /// Extensions methods relating to Bayer metadata. 13 | /// 14 | public static class BayerOperationsExtensions 15 | { 16 | /// 17 | /// Apply a processor to strip out Bayer metadata from a JPEG frame. 18 | /// 19 | /// The image context. 20 | /// The camera version. 21 | /// The active image context. 22 | public static IFrameProcessingContext StripBayerMetadata(this IFrameProcessingContext context, CameraVersion version) 23 | => context.Apply(new BayerMetaProcessor(version)); 24 | 25 | /// 26 | /// Apply a processor to apply a Demosaic to raw Bayer metadata. 27 | /// 28 | /// The image context. 29 | /// The active image context. 30 | public static IFrameProcessingContext Demosaic(this IFrameProcessingContext context) 31 | => context.Apply(new DemosaicProcessor()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/StereoMode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Native; 7 | 8 | namespace MMALSharp.Config 9 | { 10 | /// 11 | /// The Stereoscopic mode code has mainly been added for completeness. 12 | /// It requires a Raspberry Pi Compute Module with two cameras connected. 13 | /// This functionality has not been tested. 14 | /// 15 | public class StereoMode 16 | { 17 | /// 18 | /// Gets or sets the stereoscopic mode. 19 | /// 20 | public MMAL_STEREOSCOPIC_MODE_T Mode { get; set; } = MMAL_STEREOSCOPIC_MODE_T.MMAL_STEREOSCOPIC_MODE_NONE; 21 | 22 | /// 23 | /// Gets or sets a value indicating whether to half the width and height of a stereoscopic image. 24 | /// 25 | /// https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/raspicam/RaspiCamControl.c#L204 26 | public int Decimate { get; set; } 27 | 28 | /// 29 | /// Gets or sets a value indicating a swap of camera order for stereoscopic mode. 30 | /// 31 | /// https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/raspicam/RaspiCamControl.c#L205 32 | public int SwapEyes { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Effects/CustomConvolutionProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | 8 | namespace MMALSharp.Processors.Effects 9 | { 10 | /// 11 | /// A image processor allowing for user-defined kernels. 12 | /// 13 | public class CustomConvolutionProcessor : ConvolutionBase, IFrameProcessor 14 | { 15 | private readonly int _kernelWidth; 16 | private readonly int _kernelHeight; 17 | 18 | private double[,] Kernel { get; } 19 | 20 | /// 21 | /// Creates a new instance of . 22 | /// 23 | /// The user-defined kernel. 24 | /// The kernel's width. 25 | /// The kernel's height. 26 | public CustomConvolutionProcessor(double[,] kernel, int kernelWidth, int kernelHeight) 27 | { 28 | this.Kernel = kernel; 29 | 30 | _kernelWidth = kernelWidth; 31 | _kernelHeight = kernelHeight; 32 | } 33 | 34 | /// 35 | public void Apply(ImageContext context) 36 | { 37 | this.ApplyConvolution(this.Kernel, _kernelWidth, _kernelHeight, context); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/Zoom.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Config 7 | { 8 | /// 9 | /// Allows a user to specify a Region of Interest with Still captures. 10 | /// 11 | public struct Zoom 12 | { 13 | /// 14 | /// The X coordinate between 0 - 1.0. 15 | /// 16 | public double X { get; } 17 | 18 | /// 19 | /// The Y coordinate between 0 - 1.0. 20 | /// 21 | public double Y { get; } 22 | 23 | /// 24 | /// The Width value between 0 - 1.0. 25 | /// 26 | public double Width { get; } 27 | 28 | /// 29 | /// The Height value between 0 - 1.0. 30 | /// 31 | public double Height { get; } 32 | 33 | /// 34 | /// Intialises a new struct. 35 | /// 36 | /// The X coordinate. 37 | /// The Y coordinate. 38 | /// The Width value. 39 | /// The Height value. 40 | public Zoom(double x, double y, double width, double height) 41 | { 42 | X = x; 43 | Y = y; 44 | Width = width; 45 | Height = height; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Handlers 7 | { 8 | /// 9 | /// Contains the user provided image data with for a process operation. 10 | /// 11 | public class ProcessResult 12 | { 13 | /// 14 | /// Gets or sets a value indicated whether the associated process operation succeeded. 15 | /// 16 | public bool Success { get; set; } 17 | 18 | /// 19 | /// Gets or sets a message associated with this . 20 | /// 21 | public string Message { get; set; } 22 | 23 | /// 24 | /// Gets or sets a value indicating whether the end of file has been reached. 25 | /// 26 | public bool EOF { get; set; } 27 | 28 | /// 29 | /// Gets or sets the buffer feed containing the image data. 30 | /// 31 | public byte[] BufferFeed { get; set; } 32 | 33 | /// 34 | /// Gets or sets the count of bytes in the buffer used for image data. 35 | /// 36 | public int DataLength { get; set; } 37 | 38 | /// 39 | /// Gets or sets the count of bytes allocated for the buffer. 40 | /// 41 | public int AllocSize { get; set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/ICameraComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Ports.Outputs; 8 | 9 | namespace MMALSharp.Components 10 | { 11 | /// 12 | /// Represents a camera component. 13 | /// 14 | public interface ICameraComponent : IComponent 15 | { 16 | /// 17 | /// The camera's preview port. 18 | /// 19 | IOutputPort PreviewPort { get; } 20 | 21 | /// 22 | /// The camera's video port. 23 | /// 24 | IOutputPort VideoPort { get; } 25 | 26 | /// 27 | /// The camera's still port. 28 | /// 29 | IOutputPort StillPort { get; } 30 | 31 | /// 32 | /// The managed camera info component object. 33 | /// 34 | ICameraInfoComponent CameraInfo { get; } 35 | 36 | /// 37 | /// Call to initialise the camera component. 38 | /// 39 | /// A capture handler when capturing raw image frames from the camera's still port (no encoder attached). 40 | /// A capture handler when capturing raw video from the camera's video port (no encoder attached). 41 | void Initialise(IOutputCaptureHandler stillCaptureHandler = null, IOutputCaptureHandler videoCaptureHandler = null); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/MMALSharp.Demo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MMALSharp.Demo 4 | { 5 | static class Program 6 | { 7 | public static void OperationsHandler() 8 | { 9 | MMALCameraConfig.Debug = true; 10 | 11 | Console.WriteLine("Please select from an option below."); 12 | 13 | Console.WriteLine("1. Picture"); 14 | Console.WriteLine("2. Video"); 15 | Console.WriteLine("3. Utilities"); 16 | Console.WriteLine("4. Configuration"); 17 | Console.WriteLine("5. Exit"); 18 | 19 | var key = Console.ReadKey(); 20 | 21 | var imageOps = new ImageOps(); 22 | var videoOps = new VideoOps(); 23 | 24 | switch (key.KeyChar) 25 | { 26 | case '1': 27 | imageOps.Operations(); 28 | break; 29 | case '2': 30 | videoOps.Operations(); 31 | break; 32 | } 33 | } 34 | 35 | static void Main(string[] args) 36 | { 37 | Console.WriteLine(@" 38 | __ __ __ __ _ _ ___ _ 39 | | \/ | \/ | /_\ | | / __| |_ __ _ _ _ _ __ 40 | | |\/| | |\/| |/ _ \| |__\__ \ ' \/ _` | '_| '_ \ 41 | |_| |_|_| |_/_/ \_\____|___/_||_\__,_|_| | .__/ 42 | |_| 43 | "); 44 | 45 | Console.WriteLine("Welcome to the MMALSharp Demo application."); 46 | 47 | OperationsHandler(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/ProcessedFileResult.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Handlers 7 | { 8 | /// 9 | /// Represents a file that contains the image data written by a capture handler. 10 | /// 11 | public class ProcessedFileResult 12 | { 13 | /// 14 | /// Gets or sets the directory path of the file. 15 | /// 16 | public string Directory { get; set; } 17 | 18 | /// 19 | /// Gets or sets the filename without extension. 20 | /// 21 | public string Filename { get; set; } 22 | 23 | /// 24 | /// Gets or sets the file extension without the leading dot. 25 | /// 26 | public string Extension { get; set; } 27 | 28 | /// 29 | /// Creates a new instance of the class with the specified directory, filename and extension. 30 | /// 31 | /// The directory path of the file. 32 | /// The filename without extension. 33 | /// The file extension without the leading dot. 34 | public ProcessedFileResult(string directory, string filename, string extension) 35 | { 36 | this.Directory = directory; 37 | this.Filename = filename; 38 | this.Extension = extension; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/JpegThumbnail.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Config 7 | { 8 | /// 9 | /// Provides config settings for JPEG thumbnail embedding. 10 | /// 11 | public class JpegThumbnail 12 | { 13 | /// 14 | /// Enable JPEG thumbnail. 15 | /// 16 | public bool Enable { get; set; } 17 | 18 | /// 19 | /// The width of the thumbnail. 20 | /// 21 | public int Width { get; set; } 22 | 23 | /// 24 | /// The height of the thumbnail. 25 | /// 26 | public int Height { get; set; } 27 | 28 | /// 29 | /// The quality of the thumbnail. 30 | /// 31 | public int Quality { get; set; } 32 | 33 | /// 34 | /// Create a new instance of . 35 | /// 36 | /// Enable JPEG thumbnail. 37 | /// The width of the thumbnail. 38 | /// The height of the thumbnail. 39 | /// The quality of the thumbnail. 40 | public JpegThumbnail(bool enable, int width, int height, int quality) 41 | { 42 | this.Enable = enable; 43 | this.Width = width; 44 | this.Height = height; 45 | this.Quality = quality; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Inputs/OverlayPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Components; 8 | using MMALSharp.Native; 9 | 10 | namespace MMALSharp.Ports.Inputs 11 | { 12 | /// 13 | /// Represents port behaviour especially for the static overlay renderer functionality. This object overrides 14 | /// forcing it to do nothing when it receives a callback from the component. 15 | /// 16 | public unsafe class OverlayPort : InputPort 17 | { 18 | /// 19 | /// Creates a new instance of . 20 | /// 21 | /// The native pointer. 22 | /// The component this port is associated with. 23 | /// Managed unique identifier for this component. 24 | public OverlayPort(IntPtr ptr, IComponent comp, Guid guid) 25 | : base(ptr, comp, guid) 26 | { 27 | } 28 | 29 | /// 30 | /// Creates a new instance of . 31 | /// 32 | /// The port to copy data from. 33 | public OverlayPort(IPort copyFrom) 34 | : base((IntPtr)copyFrom.Ptr, copyFrom.ComponentReference, copyFrom.Guid) 35 | { 36 | } 37 | 38 | internal override void NativeInputPortCallback(MMAL_PORT_T* port, MMAL_BUFFER_HEADER_T* buffer) { } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/FastImageOutputCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Native; 8 | using MMALSharp.Ports.Outputs; 9 | 10 | namespace MMALSharp.Callbacks 11 | { 12 | /// 13 | /// A callback handler specifically for rapid image capture from the camera's video port. 14 | /// 15 | public class FastImageOutputCallbackHandler : PortCallbackHandler 16 | { 17 | /// 18 | /// Creates a new instance of . 19 | /// 20 | /// The working . 21 | /// The output port capture handler. 22 | public FastImageOutputCallbackHandler(IVideoPort port, IOutputCaptureHandler handler) 23 | : base(port, handler) 24 | { 25 | } 26 | 27 | /// 28 | public override void Callback(IBuffer buffer) 29 | { 30 | base.Callback(buffer); 31 | 32 | var eos = buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_FRAME_END) || 33 | buffer.AssertProperty(MMALBufferProperties.MMAL_BUFFER_HEADER_FLAG_EOS); 34 | 35 | if (eos && this.CaptureHandler is IFileStreamCaptureHandler) 36 | { 37 | ((IFileStreamCaptureHandler)this.CaptureHandler).NewFile(); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/MMALSharp/Native/MMALCommon.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Runtime.InteropServices; 7 | 8 | namespace MMALSharp.Native 9 | { 10 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 11 | #pragma warning disable SA1132 // Each field should be declared on its own line 12 | 13 | [StructLayout(LayoutKind.Sequential)] 14 | public struct MMAL_CORE_STATISTICS_T 15 | { 16 | private uint bufferCount, firstBufferTime, lastBufferTime, maxDelay; 17 | 18 | public uint BufferCount => bufferCount; 19 | public uint FirstBufferTime => firstBufferTime; 20 | public uint LastBufferTime => lastBufferTime; 21 | public uint MaxDelay => maxDelay; 22 | 23 | public MMAL_CORE_STATISTICS_T(uint bufferCount, uint firstBufferTime, uint lastBufferTime, uint maxDelay) 24 | { 25 | this.bufferCount = bufferCount; 26 | this.firstBufferTime = firstBufferTime; 27 | this.lastBufferTime = lastBufferTime; 28 | this.maxDelay = maxDelay; 29 | } 30 | } 31 | 32 | [StructLayout(LayoutKind.Sequential)] 33 | public struct MMAL_CORE_PORT_STATISTICS_T 34 | { 35 | private MMAL_CORE_STATISTICS_T rx, tx; 36 | 37 | public MMAL_CORE_STATISTICS_T Rx => rx; 38 | public MMAL_CORE_STATISTICS_T Tx => tx; 39 | 40 | public MMAL_CORE_PORT_STATISTICS_T(MMAL_CORE_STATISTICS_T rx, MMAL_CORE_STATISTICS_T tx) 41 | { 42 | this.rx = rx; 43 | this.tx = tx; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/IMotionCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Processors.Motion; 7 | using System; 8 | 9 | namespace MMALSharp.Handlers 10 | { 11 | /// 12 | /// Represents a capture handler which can detect motion. 13 | /// 14 | public interface IMotionCaptureHandler 15 | { 16 | /// 17 | /// The motion type associated with this MotionCaptureHandler. 18 | /// 19 | MotionType MotionType { get; set; } 20 | 21 | /// 22 | /// Call to configure motion detection. 23 | /// 24 | /// The motion configuration. 25 | /// A callback for when motion is detected. 26 | void ConfigureMotionDetection(MotionConfig config, Action onDetect); 27 | 28 | /// 29 | /// Enables motion detection. When configured, this will instruct the capture handler to detect motion. 30 | /// 31 | void EnableMotionDetection(); 32 | 33 | /// 34 | /// Disables motion detection. When configured, this will instruct the capture handler not to detect motion. 35 | /// 36 | /// When true, motion detection will continue but the OnDetect callback 37 | /// will not be invoked. Call to re-enable the callback. 38 | void DisableMotionDetection(bool disableCallbackOnly = false); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/ConnectionCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using Microsoft.Extensions.Logging; 7 | using MMALSharp.Common.Utility; 8 | 9 | namespace MMALSharp.Callbacks 10 | { 11 | /// 12 | /// Base class for connection callback handlers. 13 | /// 14 | public abstract class ConnectionCallbackHandler : IConnectionCallbackHandler 15 | { 16 | /// 17 | public IConnection WorkingConnection { get; } 18 | 19 | /// 20 | /// Creates a new instance of . 21 | /// 22 | /// The connection. 23 | protected ConnectionCallbackHandler(IConnection connection) 24 | { 25 | this.WorkingConnection = connection; 26 | } 27 | 28 | /// 29 | /// The input port callback function to carry out. 30 | /// 31 | /// The working buffer header. 32 | public virtual void InputCallback(IBuffer buffer) 33 | { 34 | if (MMALCameraConfig.Debug) 35 | { 36 | MMALLog.Logger.LogDebug("Inside Managed input port connection callback"); 37 | } 38 | } 39 | 40 | /// 41 | public virtual void OutputCallback(IBuffer buffer) 42 | { 43 | if (MMALCameraConfig.Debug) 44 | { 45 | MMALLog.Logger.LogDebug("Inside Managed output port connection callback"); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/GenericPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Callbacks; 8 | using MMALSharp.Common.Utility; 9 | using MMALSharp.Components; 10 | 11 | namespace MMALSharp.Ports 12 | { 13 | /// 14 | /// Represents a generic MMAL port of any type. 15 | /// 16 | /// The callback handler type. 17 | public class GenericPort : PortBase 18 | where TCallback : ICallbackHandler 19 | { 20 | private Resolution _resolution; 21 | 22 | /// 23 | public override Resolution Resolution 24 | { 25 | get 26 | { 27 | return _resolution; 28 | } 29 | 30 | internal set 31 | { 32 | this.NativeWidth = value.Pad().Width; 33 | this.NativeHeight = value.Pad().Height; 34 | _resolution = new Resolution(value.Width, value.Height); 35 | } 36 | } 37 | 38 | /// 39 | /// Creates a new instance of . 40 | /// 41 | /// The native pointer. 42 | /// The component this port is associated with. 43 | /// The type of port. 44 | /// Managed unique identifier for this component. 45 | public GenericPort(IntPtr ptr, IComponent comp, PortType type, Guid guid) 46 | : base(ptr, comp, type, guid) 47 | { 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/FrameAnalysisMetadata.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | namespace MMALSharp.Processors 7 | { 8 | /// 9 | /// A structure for storing frame metadata used for parallel processing by image analysis 10 | /// and effects APIs. A struct is passed by-value which makes it a threadsafe local copy. 11 | /// Pass this structure to parallel processing algorithms as a method argument to prevent 12 | /// multiple threads from accessing the same copy. 13 | /// 14 | public struct FrameAnalysisMetadata 15 | { 16 | // Members are fields rather than properties for parallel processing performance reasons. 17 | // These must be value-type fields for thread safety. Object references would not be thread safe. 18 | 19 | /// 20 | /// Frame width in pixels. 21 | /// 22 | internal int Width; 23 | 24 | /// 25 | /// Frame height in pixels. 26 | /// 27 | internal int Height; 28 | 29 | /// 30 | /// Frame stride (bytes per row). 31 | /// 32 | internal int Stride; 33 | 34 | /// 35 | /// Frame bytes per pixel. 36 | /// 37 | internal int Bpp; 38 | 39 | /// 40 | /// Width of a parallel processing cell in pixels. 41 | /// 42 | internal int CellWidth; 43 | 44 | /// 45 | /// Height of a parallel processing cell in pixels. 46 | /// 47 | internal int CellHeight; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/MMALSharp.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | MMALSharp common library. 4 | MMALSharp.Common 5 | netstandard2.0 6 | MMALSharp.Common 7 | MMALSharp.Common 8 | MMALSharp.Common 9 | Ian Auty (c) 2016-2020 10 | en-US 11 | Ian Auty 12 | raspberry-pi 13 | https://github.com/techyian/MMALSharp 14 | https://github.com/techyian/MMALSharp/blob/dev/LICENSE.txt 15 | git 16 | https://github.com/techyian/MMALSharp 17 | 0.7.0 18 | ..\..\StyleCop.Analyzers.ruleset 19 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 20 | {65a1440e-72e1-4943-b469-5cfba8cb5633} 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | All 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/SplitterStillPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using Microsoft.Extensions.Logging; 8 | using MMALSharp.Common.Utility; 9 | using MMALSharp.Components; 10 | using MMALSharp.Native; 11 | 12 | namespace MMALSharp.Ports.Outputs 13 | { 14 | /// 15 | /// Represents a splitter component still output port. 16 | /// 17 | public unsafe class SplitterStillPort : SplitterOutputPort 18 | { 19 | /// 20 | /// Creates a new instance of . 21 | /// 22 | /// The native pointer. 23 | /// The component this port is associated with. 24 | /// Managed unique identifier for this port. 25 | public SplitterStillPort(IntPtr ptr, IComponent comp, Guid guid) 26 | : base(ptr, comp, guid) 27 | { 28 | } 29 | 30 | /// 31 | /// Creates a new instance of . 32 | /// 33 | /// The port to copy data from. 34 | public SplitterStillPort(IPort copyFrom) 35 | : base((IntPtr)copyFrom.Ptr, copyFrom.ComponentReference, copyFrom.Guid) 36 | { 37 | } 38 | 39 | internal override void NativeOutputPortCallback(MMAL_PORT_T* port, MMAL_BUFFER_HEADER_T* buffer) 40 | { 41 | if (MMALCameraConfig.Debug) 42 | { 43 | MMALLog.Logger.LogDebug($"{this.Name}: In native {nameof(SplitterStillPort)} output callback"); 44 | } 45 | 46 | base.NativeOutputPortCallback(port, buffer); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/MMALSharp/IBufferQueue.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Native; 7 | 8 | namespace MMALSharp 9 | { 10 | /// 11 | /// Represents a queue of buffer headers. 12 | /// 13 | public interface IBufferQueue : IMMALObject 14 | { 15 | /// 16 | /// Native pointer to the buffer header queue this object represents. 17 | /// 18 | unsafe MMAL_QUEUE_T* Ptr { get; } 19 | 20 | /// 21 | /// Get a MMAL_BUFFER_HEADER_T from a queue. 22 | /// 23 | /// A new managed buffer header object. 24 | IBuffer GetBuffer(); 25 | 26 | /// 27 | /// Get the number of buffer headers currently in this queue. 28 | /// 29 | /// The number of buffers currently in this queue. 30 | uint QueueLength(); 31 | 32 | /// 33 | /// Waits (blocking) for a buffer header to be available in the queue and allocates it. 34 | /// 35 | /// The buffer header. 36 | IBuffer Wait(); 37 | 38 | /// 39 | /// Waits (blocking) for a buffer header to be available in the queue and allocates it. This is the same as a wait, except that it will abort in case of timeout. 40 | /// 41 | /// Number of milliseconds to wait before aborting. 42 | /// The buffer header. 43 | IBuffer TimedWait(int waitms); 44 | 45 | /// 46 | /// Puts the buffer header back into this queue. 47 | /// 48 | /// The buffer header. 49 | void Put(IBuffer buffer); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/MMALSharp.FFmpeg/MMALSharp.FFmpeg.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | FFmpeg support library for MMALSharp. 4 | MMALSharp.FFmpeg 5 | netstandard2.0 6 | MMALSharp.FFmpeg 7 | MMALSharp.FFmpeg 8 | MMALSharp 9 | Ian Auty (c) 2016-2020 10 | en-US 11 | Ian Auty 12 | raspberry-pi 13 | https://github.com/techyian/MMALSharp 14 | https://github.com/techyian/MMALSharp/blob/dev/LICENSE.txt 15 | git 16 | https://github.com/techyian/MMALSharp 17 | 0.7.0 18 | ..\..\StyleCop.Analyzers.ruleset 19 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 20 | {0600c674-e587-4267-89f3-b52ae9591f80} 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | All 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/MMALSharp.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MMALSharp.Tests 5 | net472 6 | false 7 | MMALSharp.Tests 8 | MMALSharp.Tests 9 | MMALSharp.Tests 10 | 11 | 12 | ..\..\StyleCop.Analyzers.ruleset 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | All 23 | 24 | 25 | 26 | all 27 | runtime; build; native; contentfiles; analyzers; buildtransitive 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | PreserveNewest 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/ImageContext.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Drawing.Imaging; 7 | using MMALSharp.Common.Utility; 8 | 9 | namespace MMALSharp.Common 10 | { 11 | /// 12 | /// Represents a context to hold metadata for image frames. 13 | /// 14 | public class ImageContext 15 | { 16 | // Fields are used rather than properties for hot-path performance reasons. 17 | 18 | /// 19 | /// The working data. 20 | /// 21 | public byte[] Data; 22 | 23 | /// 24 | /// Flag to indicate whether image frame is raw. 25 | /// 26 | public bool Raw; 27 | 28 | /// 29 | /// The resolution of the frame we're processing. 30 | /// 31 | public Resolution Resolution; 32 | 33 | /// 34 | /// The encoding format of the frame we're processing. 35 | /// 36 | public MMALEncoding Encoding; 37 | 38 | /// 39 | /// The pixel format of the frame we're processing. 40 | /// 41 | public MMALEncoding PixelFormat; 42 | 43 | /// 44 | /// The image format to store the processed data in. 45 | /// 46 | public ImageFormat StoreFormat; 47 | 48 | /// 49 | /// Indicates if this frame represents the end of the stream. 50 | /// 51 | public bool Eos; 52 | 53 | /// 54 | /// Indicates if this frame contains IFrame data. 55 | /// 56 | public bool IFrame; 57 | 58 | /// 59 | /// The timestamp value. 60 | /// 61 | public long? Pts; 62 | 63 | /// 64 | /// The pixel format stride. 65 | /// 66 | public int Stride; 67 | } 68 | } -------------------------------------------------------------------------------- /src/MMALSharp/MMALSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | MMALSharp brings low level access to the Raspberry Pi camera module in C#. Based on the native MMAL library, MMALSharp allows you to configure a rich set of camera/sensor related settings via an easy to use asynchronous API. 4 | MMALSharp 5 | netstandard2.0 6 | MMALSharp 7 | MMALSharp 8 | MMALSharp 9 | Ian Auty (c) 2016-2020 10 | en-US 11 | Ian Auty 12 | raspberry-pi 13 | https://github.com/techyian/MMALSharp 14 | https://github.com/techyian/MMALSharp/blob/dev/LICENSE.txt 15 | git 16 | https://github.com/techyian/MMALSharp 17 | 0.7.0 18 | ..\..\StyleCop.Analyzers.ruleset 19 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 20 | {47af9428-8246-4267-bc76-5fc648848e40} 21 | 22 | 23 | 24 | True 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | All 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/SplitterOutputPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Common.Utility; 8 | using MMALSharp.Components; 9 | 10 | namespace MMALSharp.Ports.Outputs 11 | { 12 | /// 13 | /// Represents a splitter component output port. 14 | /// 15 | public unsafe abstract class SplitterOutputPort : OutputPort 16 | { 17 | private Resolution _resolution; 18 | 19 | /// 20 | public override Resolution Resolution 21 | { 22 | get 23 | { 24 | return _resolution; 25 | } 26 | 27 | internal set 28 | { 29 | // The splitter component doesn't support resolution changes. This override has been 30 | // added in case the user wants to use the splitter component with the Image Processing 31 | // library and will use this property to inform what resolution it's running at. Applied 32 | // via port config. 33 | _resolution = new Resolution(value.Width, value.Height); 34 | } 35 | } 36 | 37 | /// 38 | /// Creates a new instance of . 39 | /// 40 | /// The native pointer. 41 | /// The component this port is associated with. 42 | /// Managed unique identifier for this port. 43 | protected SplitterOutputPort(IntPtr ptr, IComponent comp, Guid guid) 44 | : base(ptr, comp, guid) 45 | { 46 | } 47 | 48 | /// 49 | /// Creates a new instance of . 50 | /// 51 | /// The port to copy data from. 52 | protected SplitterOutputPort(IPort copyFrom) 53 | : base((IntPtr)copyFrom.Ptr, copyFrom.ComponentReference, copyFrom.Guid) 54 | { 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/MMALSharp/IBufferEvent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Native; 7 | 8 | namespace MMALSharp 9 | { 10 | /// 11 | /// Represents a buffer event format. 12 | /// 13 | public interface IBufferEvent 14 | { 15 | /// 16 | /// Native pointer that represents this event format. 17 | /// 18 | unsafe MMAL_ES_FORMAT_T* Ptr { get; } 19 | 20 | /// 21 | /// The FourCC code of the component. 22 | /// 23 | string FourCC { get; } 24 | 25 | /// 26 | /// The working bitrate of the component. 27 | /// 28 | int Bitrate { get; } 29 | 30 | /// 31 | /// The width value. 32 | /// 33 | int Width { get; } 34 | 35 | /// 36 | /// The height value. 37 | /// 38 | int Height { get; } 39 | 40 | /// 41 | /// The CropX value. 42 | /// 43 | int CropX { get; } 44 | 45 | /// 46 | /// The CropY value. 47 | /// 48 | int CropY { get; } 49 | 50 | /// 51 | /// The crop width value. 52 | /// 53 | int CropWidth { get; } 54 | 55 | /// 56 | /// The crop height value. 57 | /// 58 | int CropHeight { get; } 59 | 60 | /// 61 | /// The pixel aspect ratio numerator value. 62 | /// 63 | int ParNum { get; } 64 | 65 | /// 66 | /// The pixel aspect ratio denominator value. 67 | /// 68 | int ParDen { get; } 69 | 70 | /// 71 | /// The framerate numerator value. 72 | /// 73 | int FramerateNum { get; } 74 | 75 | /// 76 | /// The framerate denominator value. 77 | /// 78 | int FramerateDen { get; } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Inputs/IInputPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Callbacks; 7 | using MMALSharp.Handlers; 8 | using MMALSharp.Ports.Outputs; 9 | 10 | namespace MMALSharp.Ports.Inputs 11 | { 12 | /// 13 | /// Represents an input port. 14 | /// 15 | public interface IInputPort : IPort 16 | { 17 | /// 18 | /// Call to connect this input port to an output port. This method 19 | /// simply assigns the to the ConnectedReference property. 20 | /// 21 | /// The connected output port. 22 | /// The connection object. 23 | void ConnectTo(IOutputPort outputPort, IConnection connection); 24 | 25 | /// 26 | /// Call to configure an input port. 27 | /// 28 | /// The port configuration object. 29 | /// The port to copy from. 30 | /// The capture handler to assign to this port. 31 | void Configure(IMMALPortConfig config, IPort copyPort, IInputCaptureHandler handler); 32 | 33 | /// 34 | /// Enables processing on an input port. 35 | /// 36 | void Enable(); 37 | 38 | /// 39 | /// Releases an input port buffer and reads further data from user provided image data if not reached end of file. 40 | /// 41 | /// A managed buffer object. 42 | void ReleaseBuffer(IBuffer bufferImpl); 43 | 44 | /// 45 | /// Starts the input port. 46 | /// 47 | void Start(); 48 | 49 | /// 50 | /// Registers a new input callback handler with this port. 51 | /// 52 | /// The callback handler. 53 | void RegisterCallbackHandler(IInputCallbackHandler callbackHandler); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/MMALSharp.Processing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Image Processing library for MMALSharp. 5 | MMALSharp.Processing 6 | netstandard2.0 7 | MMALSharp.Processing 8 | MMALSharp.Processing 9 | MMALSharp 10 | Ian Auty (c) 2016-2020 11 | en-US 12 | Ian Auty 13 | raspberry-pi 14 | https://github.com/techyian/MMALSharp 15 | https://github.com/techyian/MMALSharp/blob/dev/LICENSE.txt 16 | git 17 | https://github.com/techyian/MMALSharp 18 | 0.7.0 19 | ..\..\StyleCop.Analyzers.ruleset 20 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 21 | {dabc9991-56ad-4235-ba86-63def12c261a} 22 | 23 | 24 | 25 | 26 | true 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | All 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/Utility/Logging.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using Microsoft.Extensions.Logging; 7 | using System; 8 | 9 | namespace MMALSharp.Common.Utility 10 | { 11 | /// 12 | /// Provides static access to the global logger. 13 | /// Credit to @snakefoot - https://github.com/NLog/NLog.Extensions.Logging/issues/379#issuecomment-569544196 14 | /// 15 | public static class MMALLog 16 | { 17 | /// 18 | /// Gets the global logger component. 19 | /// 20 | public static ILogger Logger => _logger; 21 | private static readonly MMALLogger _logger = new MMALLogger(); 22 | 23 | /// 24 | /// Responsible for getting/setting the working LoggerFactory. 25 | /// 26 | public static ILoggerFactory LoggerFactory 27 | { 28 | get => _logger.LoggerFactory; 29 | set => _logger.LoggerFactory = value; 30 | } 31 | 32 | private class MMALLogger : ILogger 33 | { 34 | public ILoggerFactory LoggerFactory 35 | { 36 | get { return _loggerFactory; } 37 | set 38 | { 39 | _loggerFactory = value; 40 | _logger = null; 41 | } 42 | } 43 | 44 | private ILoggerFactory _loggerFactory; 45 | private ILogger _logger; 46 | private ILogger Logger => _logger ?? (_logger = _loggerFactory?.CreateLogger("MMALSharp")); 47 | 48 | IDisposable ILogger.BeginScope(TState state) 49 | { 50 | return Logger?.BeginScope(state); 51 | } 52 | 53 | bool ILogger.IsEnabled(LogLevel logLevel) 54 | { 55 | return Logger?.IsEnabled(logLevel) ?? false; 56 | } 57 | 58 | void ILogger.Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 59 | { 60 | Logger?.Log(logLevel, eventId, state, exception, formatter); 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/MMALFixture.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.IO; 8 | using System.Linq; 9 | using Microsoft.Extensions.Logging; 10 | using MMALSharp.Common.Utility; 11 | using NLog.Extensions.Logging; 12 | using Xunit; 13 | 14 | namespace MMALSharp.Tests 15 | { 16 | public class MMALFixture : IDisposable 17 | { 18 | public MMALStandalone MMALStandalone = MMALStandalone.Instance; 19 | public MMALCamera MMALCamera = MMALCamera.Instance; 20 | 21 | public MMALFixture() 22 | { 23 | var loggerFactory = LoggerFactory.Create(builder => 24 | { 25 | builder 26 | .ClearProviders() 27 | .SetMinimumLevel(LogLevel.Trace) 28 | .AddNLog("NLog.config"); 29 | }); 30 | 31 | MMALLog.LoggerFactory = loggerFactory; 32 | } 33 | 34 | public void CheckAndAssertFilepath(string filepath) 35 | { 36 | if (System.IO.File.Exists(filepath)) 37 | { 38 | var length = new System.IO.FileInfo(filepath).Length; 39 | Assert.True(length > 0, $"File {filepath} has 0 bytes."); 40 | } 41 | else 42 | { 43 | Assert.True(false, $"File {filepath} was not created"); 44 | } 45 | } 46 | 47 | public void CheckAndAssertDirectory(string directory) 48 | { 49 | DirectoryInfo info = new DirectoryInfo(directory); 50 | 51 | if (info.Exists) 52 | { 53 | var files = info.EnumerateFiles(); 54 | 55 | Assert.True(files != null && files.Any()); 56 | } 57 | else 58 | { 59 | Assert.True(false, $"Directory {directory} was not created"); 60 | } 61 | } 62 | 63 | public void Dispose() 64 | { 65 | this.MMALCamera.Cleanup(); 66 | this.MMALStandalone.Cleanup(); 67 | } 68 | } 69 | 70 | [CollectionDefinition("MMALCollection")] 71 | public class MMALTestCollection : ICollectionFixture 72 | { 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/SplitterVideoPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using Microsoft.Extensions.Logging; 8 | using MMALSharp.Callbacks; 9 | using MMALSharp.Common.Utility; 10 | using MMALSharp.Components; 11 | using MMALSharp.Handlers; 12 | using MMALSharp.Native; 13 | using MMALSharp.Ports.Inputs; 14 | 15 | namespace MMALSharp.Ports.Outputs 16 | { 17 | /// 18 | /// Represents a splitter component video output port. 19 | /// 20 | public unsafe class SplitterVideoPort : SplitterOutputPort, IVideoPort 21 | { 22 | /// 23 | /// Creates a new instance of . 24 | /// 25 | /// The native pointer. 26 | /// The component this port is associated with. 27 | /// Managed unique identifier for this port. 28 | public SplitterVideoPort(IntPtr ptr, IComponent comp, Guid guid) 29 | : base(ptr, comp, guid) 30 | { 31 | } 32 | 33 | /// 34 | /// Creates a new instance of . 35 | /// 36 | /// The port to copy data from. 37 | public SplitterVideoPort(IPort copyFrom) 38 | : base((IntPtr)copyFrom.Ptr, copyFrom.ComponentReference, copyFrom.Guid) 39 | { 40 | } 41 | 42 | /// 43 | public override void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) 44 | { 45 | base.Configure(config, copyFrom, handler); 46 | 47 | this.CallbackHandler = new VideoOutputCallbackHandler(this, (IVideoCaptureHandler)handler, config.Split); 48 | } 49 | 50 | internal override void NativeOutputPortCallback(MMAL_PORT_T* port, MMAL_BUFFER_HEADER_T* buffer) 51 | { 52 | if (MMALCameraConfig.Debug) 53 | { 54 | MMALLog.Logger.LogDebug($"{this.Name}: In native {nameof(SplitterVideoPort)} output callback"); 55 | } 56 | 57 | base.NativeOutputPortCallback(port, buffer); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/Data/ImageFxData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | using MMALSharp.Native; 8 | 9 | namespace MMALSharp.Tests.Data 10 | { 11 | public class ImageFxData 12 | { 13 | public static IEnumerable Data 14 | => new List 15 | { 16 | // { Effect, throws exception } 17 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_CARTOON, false }, 18 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_BLACKBOARD, true }, 19 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_BLUR, false }, 20 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_COLOURBALANCE, false }, 21 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_COLOURPOINT, false }, 22 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_COLOURSWAP, false }, 23 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_DENOISE, false }, 24 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_EMBOSS, false }, 25 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_FILM, false }, 26 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_GPEN, false }, 27 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_HATCH, false }, 28 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_NEGATIVE, false }, 29 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_OILPAINT, false }, 30 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_PASTEL, false }, 31 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_POSTERISE, false }, 32 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_SATURATION, false }, 33 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_SKETCH, false }, 34 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_SOLARIZE, false }, 35 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_WASHEDOUT, false }, 36 | new object[] { MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_WHITEBOARD, true } 37 | }; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MMALSharp/Config/PreviewConfiguration.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Drawing; 7 | using MMALSharp.Components; 8 | using MMALSharp.Native; 9 | 10 | namespace MMALSharp.Config 11 | { 12 | /// 13 | /// Defines the settings for a component. 14 | /// 15 | public class PreviewConfiguration 16 | { 17 | /// 18 | /// Indicates whether to use full screen or windowed mode. 19 | /// 20 | public bool FullScreen { get; set; } = true; 21 | 22 | /// 23 | /// If set to true, indicates that any display scaling should disregard the aspect ratio of the frame region being displayed. 24 | /// 25 | public bool NoAspect { get; set; } 26 | 27 | /// 28 | /// Enable copy protection. 29 | /// Note: Doesn't appear to be supported by the firmware. 30 | /// 31 | public bool CopyProtect { get; set; } 32 | 33 | /// 34 | /// Specifies where the preview overlay should be drawn on the screen. 35 | /// 36 | public Rectangle PreviewWindow { get; set; } = new Rectangle(0, 0, 1024, 768); 37 | 38 | /// 39 | /// Opacity of the preview windows. Value between 1 (fully invisible) - 255 (fully opaque). 40 | /// Note: If RGBA encoding is used with the preview component then the alpha channel will be ignored. 41 | /// 42 | public int Opacity { get; set; } = 255; 43 | 44 | /// 45 | /// Sets the relative depth of the images, with greater values being in front of smaller values. 46 | /// 47 | public int Layer { get; set; } = 2; 48 | 49 | /// 50 | /// Indicates whether any flipping or rotation should be used on the overlay. 51 | /// 52 | public MMALParametersVideo.MMAL_DISPLAYTRANSFORM_T DisplayTransform { get; set; } 53 | 54 | /// 55 | /// Indicates how the image should be scaled to fit the display. 56 | /// 57 | public MMALParametersVideo.MMAL_DISPLAYMODE_T DisplayMode { get; set; } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/MMALSharp.Common/GenericExtensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | 8 | namespace MMALSharp.Common 9 | { 10 | /// 11 | /// Provides extension methods for mathematical operations. 12 | /// 13 | public static class GenericExtensions 14 | { 15 | /// 16 | /// Returns a representation of this object that is in the specified range. Too large values will be dreceased to max; too small values will be increased to min. 17 | /// 18 | /// The type of the value to be clamped. 19 | /// The value to be clamped. 20 | /// The mininum inclusive value. 21 | /// The maximum inclusive value. 22 | /// A clamped representation of the initial value. 23 | public static T Clamp(this T val, T min, T max) 24 | where T : IComparable 25 | { 26 | if (val.CompareTo(min) < 0) 27 | { 28 | return min; 29 | } 30 | 31 | if (val.CompareTo(max) > 0) 32 | { 33 | return max; 34 | } 35 | 36 | return val; 37 | } 38 | 39 | /// 40 | /// Converts a value to a value from 0.0 to 1.0. 41 | /// 42 | /// The byte value to convert. 43 | /// The converted float value. 44 | public static float ToFloat(this byte val) 45 | { 46 | return val / 255.0f; 47 | } 48 | 49 | /// 50 | /// Converts a value (0.0 to 1.0) to a value from 0 to 255. 51 | /// 52 | /// The float value to convert. 53 | /// https://stackoverflow.com/questions/1914115/converting-color-value-from-float-0-1-to-byte-0-255 54 | /// The converted byte value. 55 | public static byte ToByte(this float val) 56 | { 57 | return (byte)(val * 255.999f); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/IOutputPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Callbacks; 7 | using MMALSharp.Components; 8 | using MMALSharp.Handlers; 9 | using MMALSharp.Ports.Inputs; 10 | 11 | namespace MMALSharp.Ports.Outputs 12 | { 13 | /// 14 | /// Represents an output port. 15 | /// 16 | public interface IOutputPort : IPort 17 | { 18 | /// 19 | /// Call to configure an output port. 20 | /// 21 | /// The port configuration object. 22 | /// The port to copy from. 23 | /// The capture handler to assign to this port. 24 | void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler); 25 | 26 | /// 27 | /// Connects two components together by their input and output ports. 28 | /// 29 | /// The component we want to connect to. 30 | /// The input port of the component we want to connect to. 31 | /// Flag to use connection callback (adversely affects performance). 32 | /// The connection instance between the source output and destination input ports. 33 | IConnection ConnectTo(IDownstreamComponent component, int inputPort = 0, bool useCallback = false); 34 | 35 | /// 36 | /// Enable the port specified. 37 | /// 38 | void Start(); 39 | 40 | /// 41 | /// Release an output port buffer, get a new one from the queue and send it for processing. 42 | /// 43 | /// A managed buffer object. 44 | /// Flag that this buffer is the end of stream. 45 | void ReleaseBuffer(IBuffer bufferImpl, bool eos); 46 | 47 | /// 48 | /// Call to register a new callback handler with this port. 49 | /// 50 | /// The output callback handler. 51 | void RegisterCallbackHandler(IOutputCallbackHandler callbackHandler); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/InMemoryCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Collections.Generic; 7 | using Microsoft.Extensions.Logging; 8 | using MMALSharp.Common; 9 | using MMALSharp.Common.Utility; 10 | using MMALSharp.Processors; 11 | 12 | namespace MMALSharp.Handlers 13 | { 14 | /// 15 | /// A capture handler which stores its data to memory. 16 | /// 17 | public class InMemoryCaptureHandler : OutputCaptureHandler 18 | { 19 | private int _totalProcessed; 20 | 21 | /// 22 | /// The working data store. 23 | /// 24 | public List WorkingData { get; set; } 25 | 26 | /// 27 | /// Creates a new instance of . 28 | /// 29 | public InMemoryCaptureHandler() 30 | { 31 | this.WorkingData = new List(); 32 | } 33 | 34 | /// 35 | public override void Dispose() 36 | { 37 | MMALLog.Logger.LogInformation($"Successfully processed {Helpers.ConvertBytesToMegabytes(_totalProcessed)}."); 38 | } 39 | 40 | /// 41 | public override void Process(ImageContext context) 42 | { 43 | this.WorkingData.AddRange(context.Data); 44 | _totalProcessed += context.Data.Length; 45 | base.Process(context); 46 | } 47 | 48 | /// 49 | /// Allows us to do any further processing once the capture method has completed. Note: It is the user's responsibility to 50 | /// clear the WorkingData list after processing is complete. 51 | /// 52 | public override void PostProcess() 53 | { 54 | if (this.OnManipulate != null && this.ImageContext != null) 55 | { 56 | this.ImageContext.Data = this.WorkingData.ToArray(); 57 | this.OnManipulate(new FrameProcessingContext(this.ImageContext)); 58 | this.WorkingData = new List(this.ImageContext.Data); 59 | } 60 | } 61 | 62 | /// 63 | public override string TotalProcessed() 64 | { 65 | return $"{_totalProcessed}"; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /run-sonar.ps1: -------------------------------------------------------------------------------- 1 | # Adapted from: https://github.com/NLog/NLog.Extensions.Logging/blob/master/run-sonar.ps1 2 | 3 | $projectFile = "src\MMALSharp\MMALSharp.csproj" 4 | $sonarQubeId = "MMALSharp" 5 | $github = "techyian/MMALSharp" 6 | $baseBranch = "dev" 7 | $framework = "netstandard2.0" 8 | 9 | 10 | if ($env:APPVEYOR_REPO_NAME -eq $github) { 11 | 12 | if (-not $env:SONAR_TOKEN) { 13 | Write-warning "Sonar: not running SonarQube, no SONAR_KEY" 14 | return; 15 | } 16 | 17 | $prMode = $false; 18 | $branchMode = $false; 19 | 20 | if ($env:APPVEYOR_PULL_REQUEST_NUMBER) { 21 | # first check PR as that is on the base branch 22 | $prMode = $true; 23 | Write-Output "Sonar: on PR $env:APPVEYOR_PULL_REQUEST_NUMBER" 24 | } 25 | elseif ($env:APPVEYOR_REPO_BRANCH -eq $baseBranch) { 26 | Write-Output "Sonar: on base branch ($baseBranch)" 27 | } 28 | else { 29 | $branchMode = $true; 30 | Write-Output "Sonar: on branch $env:APPVEYOR_REPO_BRANCH" 31 | } 32 | 33 | choco install "msbuild-sonarqube-runner" -y 34 | 35 | $sonarUrl = "https://sonarcloud.io" 36 | $sonarKey = $env:SONAR_KEY 37 | $sonarToken = $env:SONAR_TOKEN 38 | $buildVersion = $env:APPVEYOR_BUILD_VERSION 39 | 40 | 41 | if ($prMode) { 42 | $pr = $env:APPVEYOR_PULL_REQUEST_NUMBER 43 | Write-Output "Sonar: Running Sonar for PR $pr" 44 | SonarScanner.MSBuild.exe begin /o:"$sonarKey" /k:"$sonarQubeId" /d:"sonar.host.url=$sonarUrl" /d:"sonar.login=$sonarToken" /v:"$buildVersion" /d:"sonar.analysis.mode=preview" /d:"sonar.github.pullRequest=$pr" /d:"sonar.github.repository=$github" /d:"sonar.github.oauth=$env:GITHUB_AUTH" 45 | } 46 | elseif ($branchMode) { 47 | $branch = $env:APPVEYOR_REPO_BRANCH; 48 | Write-Output "Sonar: Running Sonar in branch mode for branch $branch" 49 | SonarScanner.MSBuild.exe begin /o:"$sonarKey" /k:"$sonarQubeId" /d:"sonar.host.url=$sonarUrl" /d:"sonar.login=$sonarToken" /v:"$buildVersion" /d:"sonar.branch.name=$branch" 50 | } 51 | else { 52 | Write-Output "Sonar: Running Sonar in non-preview mode, on branch $env:APPVEYOR_REPO_BRANCH" 53 | SonarScanner.MSBuild.exe begin /o:"$sonarKey" /k:"$sonarQubeId" /d:"sonar.host.url=$sonarUrl" /d:"sonar.login=$sonarToken" /v:"$buildVersion" 54 | } 55 | 56 | msbuild /t:Rebuild $projectFile /p:targetFrameworks=$framework /verbosity:minimal 57 | 58 | SonarScanner.MSBuild.exe end /d:"sonar.login=$env:sonar_token" 59 | } 60 | else { 61 | Write-Output "Sonar: not running as we're on '$env:APPVEYOR_REPO_NAME'" 62 | } -------------------------------------------------------------------------------- /src/MMALSharp/Callbacks/InputPortCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using Microsoft.Extensions.Logging; 7 | using MMALSharp.Common.Utility; 8 | using MMALSharp.Handlers; 9 | using MMALSharp.Ports.Inputs; 10 | 11 | namespace MMALSharp.Callbacks 12 | { 13 | /// 14 | /// Represents an input port callback handler. 15 | /// 16 | /// The input port type linked to this callback handler. 17 | /// The capture handler type linked to this callback handler. 18 | public abstract class InputPortCallbackHandler : IInputCallbackHandler 19 | where TPort : IInputPort 20 | where TCaptureHandler : IInputCaptureHandler 21 | { 22 | /// 23 | /// The working port. 24 | /// 25 | public TPort WorkingPort { get; } 26 | 27 | /// 28 | /// The active capture handler. 29 | /// 30 | public TCaptureHandler CaptureHandler { get; } 31 | 32 | /// 33 | /// Creates a new instance of . 34 | /// 35 | /// The working port. 36 | /// The input port capture handler. 37 | protected InputPortCallbackHandler(TPort port, TCaptureHandler handler) 38 | { 39 | this.WorkingPort = port; 40 | this.CaptureHandler = handler; 41 | } 42 | 43 | /// 44 | /// Responsible for feeding data into the input port. 45 | /// 46 | /// The working buffer. 47 | /// A based on the result of the operation. 48 | public virtual ProcessResult CallbackWithResult(IBuffer buffer) 49 | { 50 | if (MMALCameraConfig.Debug) 51 | { 52 | MMALLog.Logger.LogDebug($"In managed {this.WorkingPort.PortType.GetPortType()} callback"); 53 | } 54 | 55 | MMALLog.Logger.LogInformation($"Feeding: {Helpers.ConvertBytesToMegabytes(buffer.AllocSize)}. Total processed: {this.CaptureHandler?.TotalProcessed()}."); 56 | 57 | return this.CaptureHandler?.Process(buffer.AllocSize); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/MMALSplitterComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Handlers; 8 | using MMALSharp.Native; 9 | using MMALSharp.Ports; 10 | using MMALSharp.Ports.Inputs; 11 | using MMALSharp.Ports.Outputs; 12 | 13 | namespace MMALSharp.Components 14 | { 15 | /// 16 | /// The Splitter Component can be connected to either the camera's still or video port and in turn, it 17 | /// provides an additional 4 output ports which can be used to produce multiple image/video outputs. 18 | /// 19 | public class MMALSplitterComponent : MMALDownstreamHandlerComponent 20 | { 21 | /// 22 | /// Creates a new instance of . Defaults to video port behaviour; configure the output port 23 | /// using as a generic constraint if this splitter is intended to be connected to the camera's still port. 24 | /// 25 | public unsafe MMALSplitterComponent() 26 | : base(MMALParameters.MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER) 27 | { 28 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 29 | 30 | for (var i = 0; i < 4; i++) 31 | { 32 | this.Outputs.Add(new SplitterVideoPort((IntPtr)(&(*this.Ptr->Output[i])), this, Guid.NewGuid())); 33 | } 34 | } 35 | 36 | /// 37 | public override IDownstreamComponent ConfigureInputPort(IMMALPortConfig config, IPort copyPort, IInputCaptureHandler handler) 38 | { 39 | var bufferNum = Math.Max(Math.Max(this.Inputs[0].BufferNumRecommended, 3), config.BufferNum); 40 | 41 | config = new MMALPortConfig( 42 | config.EncodingType, 43 | config.PixelFormat, 44 | config.Quality, 45 | config.Bitrate, 46 | config.Timeout, 47 | config.Split, 48 | config.StoreMotionVectors, 49 | config.Width, 50 | config.Height, 51 | config.Framerate, 52 | config.ZeroCopy, 53 | bufferNum, 54 | config.BufferSize, 55 | config.Crop); 56 | 57 | base.ConfigureInputPort(config, copyPort, handler); 58 | 59 | return this; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/InputCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.IO; 7 | using MMALSharp.Common.Utility; 8 | 9 | namespace MMALSharp.Handlers 10 | { 11 | /// 12 | /// Represents an InputCaptureHandler which is responsible for feeding data from a stream. 13 | /// 14 | public class InputCaptureHandler : IInputCaptureHandler 15 | { 16 | /// 17 | /// Gets or sets the stream to retrieve input data from. 18 | /// 19 | public Stream CurrentStream { get; } 20 | 21 | /// 22 | /// The total amount of data processed by this . 23 | /// 24 | public int Processed { get; protected set; } 25 | 26 | /// 27 | /// Creates a new instance of the class with the specified input stream, output directory and output filename extension. 28 | /// 29 | /// The stream to retrieve input data from. 30 | public InputCaptureHandler(Stream inputStream) 31 | { 32 | this.CurrentStream = inputStream; 33 | } 34 | 35 | /// 36 | /// When overridden in a derived class, returns user provided image data. 37 | /// 38 | /// The count of bytes to return at most in the . 39 | /// A object containing the user provided image data. 40 | public virtual ProcessResult Process(uint allocSize) 41 | { 42 | var buffer = new byte[allocSize]; 43 | 44 | var read = this.CurrentStream.Read(buffer, 0, (int)allocSize); 45 | 46 | this.Processed += read; 47 | 48 | if (read == 0) 49 | { 50 | return new ProcessResult { Success = true, BufferFeed = buffer, EOF = true, DataLength = read }; 51 | } 52 | 53 | return new ProcessResult { Success = true, BufferFeed = buffer, DataLength = read }; 54 | } 55 | 56 | /// 57 | public void Dispose() 58 | { 59 | this.CurrentStream?.Dispose(); 60 | } 61 | 62 | /// 63 | public string TotalProcessed() 64 | { 65 | return $"{Helpers.ConvertBytesToMegabytes(this.Processed)}"; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Bayer/BayerMetaProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Text; 8 | using MMALSharp.Common; 9 | 10 | namespace MMALSharp.Processors 11 | { 12 | /// 13 | /// The BayerMetaProcessor is used to strip Bayer metadata from a JPEG image frame via the Image Processing API. 14 | /// 15 | public class BayerMetaProcessor : IFrameProcessor 16 | { 17 | /// 18 | /// The camera version being used. 19 | /// 20 | public CameraVersion CameraVersion { get; } 21 | 22 | /// 23 | /// The length of the metadata for the OmniVision OV5647. 24 | /// 25 | public const int BayerMetaLengthV1 = 6404096; 26 | 27 | /// 28 | /// The length of the metadata for the Sony IMX219. 29 | /// 30 | public const int BayerMetaLengthV2 = 10270208; 31 | 32 | /// 33 | /// Initialises a new instance of . 34 | /// 35 | /// The camera version you're using. 36 | public BayerMetaProcessor(CameraVersion camVersion) 37 | { 38 | this.CameraVersion = camVersion; 39 | } 40 | 41 | /// 42 | public void Apply(ImageContext context) 43 | { 44 | byte[] array = null; 45 | 46 | switch (this.CameraVersion) 47 | { 48 | case CameraVersion.OV5647: 49 | array = new byte[BayerMetaLengthV1]; 50 | Array.Copy(context.Data, context.Data.Length - BayerMetaLengthV1, array, 0, BayerMetaLengthV1); 51 | break; 52 | case CameraVersion.IMX219: 53 | array = new byte[BayerMetaLengthV2]; 54 | Array.Copy(context.Data, context.Data.Length - BayerMetaLengthV2, array, 0, BayerMetaLengthV2); 55 | break; 56 | } 57 | 58 | byte[] meta = new byte[4]; 59 | Array.Copy(array, 0, meta, 0, 4); 60 | 61 | if (Encoding.ASCII.GetString(meta) != "BRCM") 62 | { 63 | throw new Exception("Could not find Bayer metadata in header"); 64 | } 65 | 66 | context.Data = new byte[array.Length]; 67 | Array.Copy(array, context.Data, array.Length); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Motion/MotionConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | 8 | namespace MMALSharp.Processors.Motion 9 | { 10 | /// 11 | /// This class is used to store user preferences when detecting motion between two image frames. 12 | /// 13 | public class MotionConfig 14 | { 15 | /// 16 | /// Implements the logic used to detect motion. 17 | /// 18 | public IMotionAlgorithm MotionAlgorithm { get; set; } 19 | 20 | /// 21 | /// The frequency at which the test frame is updated. The test frame is the baseline against 22 | /// which the current frame is compared to detect motion. 23 | /// 24 | public TimeSpan TestFrameInterval { get; set; } 25 | 26 | /// 27 | /// The minimum duration with no motion detection events before the test frame will update. 28 | /// 29 | public TimeSpan TestFrameRefreshCooldown { get; set; } 30 | 31 | /// 32 | /// The name of a BMP file to apply as a motion-detection mask. The file must match the raw stream's 33 | /// width, height, and color depth. Black pixels (RGB 0,0,0) are not tested for motion. 34 | /// 35 | public string MotionMaskPathname { get; set; } 36 | 37 | /// 38 | /// Creates a new instance of . 39 | /// 40 | /// An instance of the motion detection algorithm implementation. 41 | /// Frequency at which the test frame is updated. The default is 10 seconds. 42 | /// The minimum duration with no motion detection before the test frame updates. The default is 3 seconds. 43 | /// Pathname to an optional motion-detection mask bitmap. 44 | public MotionConfig( 45 | IMotionAlgorithm algorithm, 46 | TimeSpan testFrameInterval = default, 47 | TimeSpan testFrameCooldown = default, 48 | string motionMaskPathname = null) 49 | { 50 | this.MotionAlgorithm = algorithm; 51 | this.TestFrameInterval = testFrameInterval.Equals(TimeSpan.Zero) ? TimeSpan.FromSeconds(10) : testFrameInterval; 52 | this.TestFrameRefreshCooldown = testFrameCooldown.Equals(TimeSpan.Zero) ? TimeSpan.FromSeconds(3) : testFrameCooldown; 53 | this.MotionMaskPathname = motionMaskPathname; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Motion/IMotionAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using MMALSharp.Handlers; 8 | 9 | namespace MMALSharp.Processors.Motion 10 | { 11 | /// 12 | /// Represents a frame-difference-based motion detection algorithm. 13 | /// 14 | public interface IMotionAlgorithm 15 | { 16 | /// 17 | /// Activates analysis mode. 18 | /// 19 | /// Optional. If specified, the algorithm analyses each frame, marking cell corners, 20 | /// outlining cells with motion, and altering the output to grayscale highlights of the calculated diff per pixel. 21 | void EnableAnalysis(IOutputCaptureHandler handler); 22 | 23 | /// 24 | /// Deactivates analysis mode. 25 | /// 26 | void DisableAnalysis(); 27 | 28 | /// 29 | /// Invoked after the buffer's is available 30 | /// for the first time and frame metadata has been collected. Allows the algorithm 31 | /// to modify the test frame, prepare matching local buffers, etc. 32 | /// 33 | /// The invoking this method. 34 | /// Properties of the frame. 35 | /// A sample context object which should be stored to feed to a capture handler if analysis is enabled. 36 | void FirstFrameCompleted(FrameDiffDriver driver, FrameAnalysisMetadata metadata, ImageContext contextTemplate); 37 | 38 | /// 39 | /// Invoked when has a full test frame and a 40 | /// new full comparison frame available. 41 | /// 42 | /// The invoking this method. 43 | /// Properties of the frame. 44 | /// Indicates whether motion was detected. 45 | bool DetectMotion(FrameDiffDriver driver, FrameAnalysisMetadata metadata); 46 | 47 | /// 48 | /// Invoked when has been reset. The algorithm should also 49 | /// reset stateful data, if any. 50 | /// 51 | /// The invoking this method. 52 | /// Properties of the frame. 53 | void ResetAnalyser(FrameDiffDriver driver, FrameAnalysisMetadata metadata); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/MMALSharp/Components/MMALIspComponent.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using MMALSharp.Ports.Inputs; 8 | using MMALSharp.Ports.Outputs; 9 | using static MMALSharp.Native.MMALParameters; 10 | 11 | namespace MMALSharp.Components 12 | { 13 | /// 14 | /// This component wraps the ISP (Image Sensor Processor) hardware block to 15 | /// offer hardware accelerated format conversion and resizing. 16 | /// It has one input port taking Bayer, YUV or RGB images in numerous different formats. 17 | /// It has two output ports: 18 | /// Port 361 supports various RGB and YUV formats. 19 | /// Port 362 is off the low res resizer which can only downscale.Due to this 20 | /// port 362 must be at a lower resolution to port 361. If set to a higher resolution 21 | /// then the port will effectively be disabled and no ouput produced.It also doesn't have 22 | /// the colour conversion block, and so only supports YUV formats. 23 | /// https://github.com/raspberrypi/firmware/blob/master/documentation/ilcomponents/isp.html 24 | /// 25 | public class MMALIspComponent : MMALDownstreamHandlerComponent 26 | { 27 | /// 28 | /// Creates a new instance of the class that can be used to change the size 29 | /// and the pixel format of resulting frames. 30 | /// 31 | public unsafe MMALIspComponent() 32 | : base(MMAL_COMPONENT_ISP) 33 | { 34 | // Default to use still image port behaviour. 35 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 36 | 37 | for (var i = 0; i < this.Ptr->OutputNum; i++) 38 | { 39 | this.Outputs.Add(new StillPort((IntPtr)(&(*this.Ptr->Output[i])), this, Guid.NewGuid())); 40 | } 41 | } 42 | 43 | /// 44 | /// Creates a new instance of the class that can be used to change the size 45 | /// and the pixel format of resulting frames. 46 | /// 47 | /// The user defined output port type. 48 | public unsafe MMALIspComponent(Type outputPortType) 49 | : base(MMAL_COMPONENT_ISP) 50 | { 51 | this.Inputs.Add(new InputPort((IntPtr)(&(*this.Ptr->Input[0])), this, Guid.NewGuid())); 52 | 53 | for (var i = 0; i < this.Ptr->OutputNum; i++) 54 | { 55 | this.Outputs.Add((IOutputPort)Activator.CreateInstance(outputPortType, (IntPtr)(&(*this.Ptr->Output[i])), this, Guid.NewGuid())); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/IMMALPortConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Drawing; 8 | using MMALSharp.Common; 9 | using MMALSharp.Config; 10 | 11 | namespace MMALSharp.Ports 12 | { 13 | /// 14 | /// Represents a port configuration object. 15 | /// 16 | public interface IMMALPortConfig 17 | { 18 | /// 19 | /// The encoding type this output port will send data in. 20 | /// 21 | MMALEncoding EncodingType { get; } 22 | 23 | /// 24 | /// The pixel format this output port will send data in. 25 | /// 26 | MMALEncoding PixelFormat { get; } 27 | 28 | /// 29 | /// User provided width of output frame. 30 | /// 31 | int Width { get; } 32 | 33 | /// 34 | /// User provided height of output frame. 35 | /// 36 | int Height { get; } 37 | 38 | /// 39 | /// The framerate of the outputted data. 40 | /// 41 | double Framerate { get; } 42 | 43 | /// 44 | /// The quality of our outputted data. 45 | /// 46 | int Quality { get; } 47 | 48 | /// 49 | /// The bitrate we are sending data at. 50 | /// 51 | int Bitrate { get; } 52 | 53 | /// 54 | /// Instruct MMAL to not copy buffers to ARM memory (useful for large buffers and handling raw data). 55 | /// 56 | bool ZeroCopy { get; } 57 | 58 | /// 59 | /// Time that processing shall stop. Relevant for video recording. 60 | /// 61 | DateTime? Timeout { get; } 62 | 63 | /// 64 | /// Requested number of buffer headers. 65 | /// 66 | int BufferNum { get; } 67 | 68 | /// 69 | /// Requested size of buffer headers. 70 | /// 71 | int BufferSize { get; } 72 | 73 | /// 74 | /// The Region of Interest requested. 75 | /// 76 | Rectangle? Crop { get; } 77 | 78 | /// 79 | /// Video split configuration object. 80 | /// 81 | Split Split { get; } 82 | 83 | /// 84 | /// Indicates whether motion vector data should be stored to a separate output stream. Only applies to Video recording. 85 | /// 86 | bool StoreMotionVectors { get; } 87 | 88 | /// 89 | /// User provided name for port. Helps with debugging. 90 | /// 91 | string UserPortName { get; } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/MMALSharp/Native/MMALQueue.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Runtime.InteropServices; 7 | 8 | namespace MMALSharp.Native 9 | { 10 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 11 | 12 | public static class MMALQueue 13 | { 14 | #pragma warning disable IDE1006 // Naming Styles 15 | // MMAL_QUEUE_T* 16 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_create", CallingConvention = CallingConvention.Cdecl)] 17 | public static extern unsafe MMAL_QUEUE_T* mmal_queue_create(); 18 | 19 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_put", CallingConvention = CallingConvention.Cdecl)] 20 | public static extern unsafe void mmal_queue_put(MMAL_QUEUE_T* ptr, MMAL_BUFFER_HEADER_T* header); 21 | 22 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_put_back", CallingConvention = CallingConvention.Cdecl)] 23 | public static extern unsafe void mmal_queue_put_back(MMAL_QUEUE_T* ptr, MMAL_BUFFER_HEADER_T* header); 24 | 25 | // MMAL_QUEUE_T* 26 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_get", CallingConvention = CallingConvention.Cdecl)] 27 | public static extern unsafe MMAL_BUFFER_HEADER_T* mmal_queue_get(MMAL_QUEUE_T* ptr); 28 | 29 | // MMAL_QUEUE_T* 30 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_wait", CallingConvention = CallingConvention.Cdecl)] 31 | public static extern unsafe MMAL_BUFFER_HEADER_T* mmal_queue_wait(MMAL_QUEUE_T* ptr); 32 | 33 | // MMAL_QUEUE_T* 34 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_timedwait", CallingConvention = CallingConvention.Cdecl)] 35 | public static extern unsafe MMAL_BUFFER_HEADER_T* mmal_queue_timedwait(MMAL_QUEUE_T* ptr, int waitms); 36 | 37 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_length", CallingConvention = CallingConvention.Cdecl)] 38 | public static extern unsafe uint mmal_queue_length(MMAL_QUEUE_T* ptr); 39 | 40 | [DllImport("libmmal.so", EntryPoint = "mmal_queue_destroy", CallingConvention = CallingConvention.Cdecl)] 41 | public static extern unsafe void mmal_queue_destroy(MMAL_QUEUE_T* ptr); 42 | #pragma warning restore IDE1006 // Naming Styles 43 | } 44 | 45 | [StructLayout(LayoutKind.Sequential)] 46 | public unsafe struct MMAL_QUEUE_T 47 | { 48 | private uint length; 49 | private MMAL_BUFFER_HEADER_T* first; 50 | private MMAL_BUFFER_HEADER_T** last; 51 | 52 | public uint Length => length; 53 | public MMAL_BUFFER_HEADER_T* First => first; 54 | public MMAL_BUFFER_HEADER_T** Last => last; 55 | 56 | public MMAL_QUEUE_T(uint length, MMAL_BUFFER_HEADER_T* first, MMAL_BUFFER_HEADER_T** last) 57 | { 58 | this.length = length; 59 | this.first = first; 60 | this.last = last; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/OutputCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Drawing.Imaging; 8 | using MMALSharp.Common; 9 | using MMALSharp.Processors; 10 | 11 | namespace MMALSharp.Handlers 12 | { 13 | /// 14 | /// Represents an OutputCaptureHandler which is responsible for storing frames processed by a component. 15 | /// 16 | public abstract class OutputCaptureHandler : IOutputCaptureHandler 17 | { 18 | /// 19 | /// A callback for use with the Image Processing API. 20 | /// 21 | protected Action OnManipulate { get; set; } 22 | 23 | /// 24 | /// A callback for use with the Image Analysis API. 25 | /// 26 | protected Func OnAnalyse { get; set; } 27 | 28 | /// 29 | /// An ImageContext providing metadata for image data. 30 | /// 31 | protected ImageContext ImageContext { get; set; } 32 | 33 | /// 34 | /// The image format to save manipulated files in. 35 | /// 36 | protected ImageFormat StoreFormat { get; set; } 37 | 38 | /// 39 | public abstract void Dispose(); 40 | 41 | /// 42 | public abstract string TotalProcessed(); 43 | 44 | /// 45 | /// The total amount of data that has been processed by this capture handler. 46 | /// 47 | protected int Processed { get; set; } 48 | 49 | /// 50 | /// Used to process the image data from an output port. Users who extend this class should call the base class 51 | /// to ensure the ImageContext property is assigned with the current frame's context. 52 | /// 53 | /// Contains the data and metadata for an image frame. 54 | public virtual void Process(ImageContext context) 55 | { 56 | this.ImageContext = context; 57 | } 58 | 59 | /// 60 | /// Allows us to do any further processing once the capture method has completed. 61 | /// 62 | public virtual void PostProcess() 63 | { 64 | } 65 | 66 | /// 67 | /// Allows manipulation of the image frame. 68 | /// 69 | /// A delegate to the manipulation you wish to carry out. 70 | /// The image format to save manipulated files in, or null to return raw data. 71 | public void Manipulate(Action context, ImageFormat storeFormat) 72 | { 73 | this.OnManipulate = context; 74 | this.StoreFormat = storeFormat; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/MMALSharp.FFmpeg/VideoUtilities.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Handlers; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | 10 | namespace MMALSharp.FFmpeg 11 | { 12 | /// 13 | /// This class provides utility methods for video capturing and converting based on FFmpeg. 14 | /// 15 | public static class VideoUtilities 16 | { 17 | /// 18 | /// Useful for Timelapse captures. Enables you to convert a list of images associated with an ImageStreamCaptureHandler to a video. 19 | /// 20 | /// The list of images we wish to process. 21 | /// The target directory we want to save the video to. 22 | /// The framerate in fps to set as -framerate parameter for FFmpeg. 23 | public static void ImagesToVideo(this ImageStreamCaptureHandler result, string targetDirectory, int fps) 24 | { 25 | var process = new Process 26 | { 27 | StartInfo = 28 | { 29 | UseShellExecute = false, 30 | CreateNoWindow = true, 31 | FileName = "ffmpeg" 32 | } 33 | }; 34 | 35 | if (result.ProcessedFiles.Count == 0) 36 | return; 37 | 38 | // Create temporary directory and copy all files in the capture handler to it. 39 | var tempDirectory = result.ProcessedFiles.FirstOrDefault().Directory.TrimEnd('/') + "/mmalsharptemp/"; 40 | var extension = result.ProcessedFiles.FirstOrDefault().Extension; 41 | 42 | try 43 | { 44 | System.IO.Directory.CreateDirectory(tempDirectory); 45 | 46 | foreach (var tuple in result.ProcessedFiles) 47 | { 48 | System.IO.File.Copy($"{tuple.Directory.TrimEnd('/')}/{tuple.Filename.TrimEnd('.')}.{tuple.Extension}", $"{tempDirectory}{tuple.Filename.TrimEnd('.')}.{tuple.Extension}"); 49 | } 50 | 51 | targetDirectory.TrimEnd('/'); 52 | 53 | if (fps == 0) 54 | { 55 | // Default to 25fps - FFmpeg defaults to this value if nothing is specified 56 | fps = 25; 57 | } 58 | 59 | process.StartInfo.Arguments = $"-framerate {fps} -f image2 -pattern_type glob -y -i {tempDirectory + "'*." + extension + "'"} {targetDirectory}/out.avi"; 60 | process.Start(); 61 | process.WaitForExit(); 62 | } 63 | finally 64 | { 65 | // Make sure we try to cleanup even if error occurs. 66 | if (System.IO.Directory.Exists(tempDirectory)) 67 | { 68 | System.IO.Directory.Delete(tempDirectory, true); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/MMALSharp.Demo/VideoOps.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using MMALSharp.Common; 5 | using MMALSharp.Components; 6 | using MMALSharp.Handlers; 7 | using MMALSharp.Native; 8 | using MMALSharp.Ports; 9 | 10 | namespace MMALSharp.Demo 11 | { 12 | public class VideoOps : OpsBase 13 | { 14 | public override void Operations() 15 | { 16 | Console.WriteLine("\nVideo Operations:"); 17 | 18 | Console.WriteLine("1. Take Video"); 19 | 20 | var key = Console.ReadKey(); 21 | var formats = this.ParsePixelFormat(); 22 | 23 | switch (key.KeyChar) 24 | { 25 | case '1': 26 | this.TakeVideoOperations(formats.Item1, formats.Item2); 27 | break; 28 | } 29 | 30 | Program.OperationsHandler(); 31 | } 32 | 33 | private void TakeVideoOperations(MMALEncoding encoding, MMALEncoding pixelFormat) 34 | { 35 | Console.WriteLine("\nPlease enter a file extension."); 36 | var extension = Console.ReadLine(); 37 | Console.WriteLine("\nPlease enter the bitrate value."); 38 | var bitrate = Console.ReadLine(); 39 | Console.WriteLine("\nPlease enter the number of seconds to record for."); 40 | var seconds = Console.ReadLine(); 41 | 42 | int intBitrate = 0, intSeconds = 0; 43 | 44 | if (!int.TryParse(bitrate, out intBitrate) || !int.TryParse(seconds, out intSeconds)) 45 | { 46 | Console.WriteLine("Invalid values entered, please try again."); 47 | this.TakeVideoOperations(encoding, pixelFormat); 48 | } 49 | 50 | this.TakeVideoManual(extension, encoding, pixelFormat, intBitrate, intSeconds).GetAwaiter().GetResult(); 51 | } 52 | 53 | private async Task TakeVideoManual(string extension, MMALEncoding encoding, MMALEncoding pixelFormat, int bitrate, int seconds) 54 | { 55 | using (var vidCaptureHandler = new VideoStreamCaptureHandler($"/home/pi/videos/", extension)) 56 | using (var vidEncoder = new MMALVideoEncoder()) 57 | using (var renderer = new MMALVideoRenderer()) 58 | { 59 | this.Cam.ConfigureCameraSettings(); 60 | 61 | var portConfig = new MMALPortConfig(encoding, pixelFormat, bitrate: bitrate); 62 | 63 | vidEncoder.ConfigureOutputPort(portConfig, vidCaptureHandler); 64 | 65 | this.Cam.Camera.VideoPort.ConnectTo(vidEncoder); 66 | this.Cam.Camera.PreviewPort.ConnectTo(renderer); 67 | 68 | // Camera warm up time 69 | await Task.Delay(2000); 70 | 71 | var cts = new CancellationTokenSource(TimeSpan.FromSeconds(seconds)); 72 | 73 | await this.Cam.ProcessAsync(this.Cam.Camera.VideoPort, cts.Token); 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.Extensions.Logging; 3 | using MMALSharp.Common; 4 | using MMALSharp.Common.Utility; 5 | using MMALSharp.Components; 6 | using MMALSharp.Config; 7 | using MMALSharp.Native; 8 | 9 | namespace MMALSharp.Tests 10 | { 11 | public class TestHelper 12 | { 13 | public static void SetConfigurationDefaults() 14 | { 15 | MMALCameraConfig.Debug = true; 16 | MMALCameraConfig.Brightness = 70; 17 | MMALCameraConfig.Sharpness = 60; 18 | MMALCameraConfig.Contrast = 60; 19 | MMALCameraConfig.Saturation = 50; 20 | MMALCameraConfig.AwbGainsB = 0; 21 | MMALCameraConfig.AwbGainsR = 0; 22 | MMALCameraConfig.AwbMode = MMAL_PARAM_AWBMODE_T.MMAL_PARAM_AWBMODE_AUTO; 23 | MMALCameraConfig.ColourFx = default(ColourEffects); 24 | MMALCameraConfig.ExposureCompensation = -1; 25 | MMALCameraConfig.ExposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_T.MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; 26 | MMALCameraConfig.ExposureMode = MMAL_PARAM_EXPOSUREMODE_T.MMAL_PARAM_EXPOSUREMODE_AUTO; 27 | MMALCameraConfig.ROI = default(Zoom); 28 | MMALCameraConfig.ISO = 0; 29 | MMALCameraConfig.StatsPass = false; 30 | MMALCameraConfig.Flips = MMAL_PARAM_MIRROR_T.MMAL_PARAM_MIRROR_NONE; 31 | MMALCameraConfig.ImageFx = MMAL_PARAM_IMAGEFX_T.MMAL_PARAM_IMAGEFX_NONE; 32 | MMALCameraConfig.Rotation = 0; 33 | MMALCameraConfig.DrcLevel = MMAL_PARAMETER_DRC_STRENGTH_T.MMAL_PARAMETER_DRC_STRENGTH_OFF; 34 | MMALCameraConfig.ShutterSpeed = 0; 35 | MMALCameraConfig.SensorMode = MMALSensorMode.Mode0; 36 | MMALCameraConfig.VideoStabilisation = true; 37 | MMALCameraConfig.Framerate = 10; 38 | MMALCameraConfig.Encoding = MMALEncoding.OPAQUE; 39 | MMALCameraConfig.EncodingSubFormat = MMALEncoding.I420; 40 | MMALCameraConfig.VideoColorSpace = MMALEncoding.MMAL_COLOR_SPACE_ITUR_BT709; 41 | MMALCameraConfig.InlineMotionVectors = false; 42 | MMALCameraConfig.Resolution = Resolution.As03MPixel; 43 | MMALCameraConfig.AnalogGain = 0; 44 | MMALCameraConfig.DigitalGain = 0; 45 | MMALCameraConfig.Annotate = null; 46 | } 47 | 48 | public static void CleanDirectory(string directory) 49 | { 50 | try 51 | { 52 | var files = Directory.GetFiles(directory); 53 | 54 | // Clear directory first 55 | foreach (string file in files) 56 | { 57 | File.Delete(file); 58 | } 59 | } 60 | catch 61 | { 62 | } 63 | } 64 | 65 | public static void BeginTest(string name) => MMALLog.Logger.LogInformation($"Running test: {name}."); 66 | 67 | public static void BeginTest(string name, string encodingType, string pixelFormat) 68 | => MMALLog.Logger.LogInformation($"Running test: {name}. Encoding type: {encodingType}. Pixel format: {pixelFormat}."); 69 | } 70 | } -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Effects/EdgeDetection.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using System; 8 | using System.Diagnostics; 9 | 10 | namespace MMALSharp.Processors.Effects 11 | { 12 | /// 13 | /// Represents the strength of the Edge Detection algorithm. 14 | /// 15 | public enum EDStrength 16 | { 17 | /// 18 | /// Low strength. 19 | /// 20 | Low = 0, 21 | 22 | /// 23 | /// Medium strength. 24 | /// 25 | Medium, 26 | 27 | /// 28 | /// High strength. 29 | /// 30 | High 31 | } 32 | 33 | /// 34 | /// A kernel based image processor used to apply Edge detection convolution. 35 | /// 36 | public class EdgeDetection : ConvolutionBase, IFrameProcessor 37 | { 38 | private const int _kernelWidth = 3; 39 | private const int _kernelHeight = 3; 40 | 41 | private readonly double[][,] _kernels = 42 | { 43 | new double[,] // 0 - Low 44 | { 45 | { -1, 0, 1 }, 46 | { 0, 0, 0 }, 47 | { 1, 0, -1 } 48 | }, 49 | new double[,] // 1 - Medium 50 | { 51 | { 0, 1, 0 }, 52 | { 1, -4, 1 }, 53 | { 0, 1, 0 } 54 | }, 55 | new double[,] // 2 - High 56 | { 57 | { -1, -1, -1 }, 58 | { -1, 8, -1 }, 59 | { -1, -1, -1 } 60 | }, 61 | }; 62 | 63 | private readonly int _kernelType; 64 | 65 | /// 66 | /// Creates a new instance of processor used to apply Edge detection convolution. 67 | /// 68 | /// The Edge detection strength. 69 | public EdgeDetection(EDStrength strength) 70 | : base() 71 | { 72 | _kernelType = (int)strength; 73 | } 74 | 75 | /// 76 | /// Creates a new instance of processor used to apply Edge detection convolution. 77 | /// 78 | /// The Edge detection strength. 79 | /// The number of columns to divide the image into. 80 | /// The number of rows to divide the image into. 81 | public EdgeDetection(EDStrength strength, int horizontalCellCount, int verticalCellCount) 82 | : base(horizontalCellCount, verticalCellCount) 83 | { 84 | _kernelType = (int)strength; 85 | } 86 | 87 | /// 88 | public void Apply(ImageContext context) 89 | { 90 | this.ApplyConvolution(_kernels[_kernelType], _kernelWidth, _kernelHeight, context); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Processors/Effects/GaussianProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using MMALSharp.Common; 7 | using System; 8 | using System.Diagnostics; 9 | 10 | namespace MMALSharp.Processors.Effects 11 | { 12 | /// 13 | /// Represents the matrix to use when applying a Gaussian blur convolution to an image frame. 14 | /// 15 | public enum GaussianMatrix 16 | { 17 | /// 18 | /// Use a 3x3 matrix. 19 | /// 20 | Matrix3x3 = 0, 21 | 22 | /// 23 | /// Use a 5x5 matrix. 24 | /// 25 | Matrix5x5, 26 | } 27 | 28 | /// 29 | /// A image processor used to apply a Gaussian blur effect. 30 | /// 31 | public class GaussianProcessor : ConvolutionBase, IFrameProcessor 32 | { 33 | private readonly int _kernelType; 34 | 35 | private readonly double[][,] _kernels = 36 | { 37 | new double[3, 3] // 0 - Matrix3x3 38 | { 39 | { 0.0625, 0.125, 0.0625 }, 40 | { 0.125, 0.25, 0.125 }, 41 | { 0.0625, 0.125, 0.0625 }, 42 | }, 43 | new double[5, 5] // 1 - Matrix5x5 44 | { 45 | { 0.00390625, 0.015625, 0.0234375, 0.015625, 0.00390625 }, 46 | { 0.015625, 0.0625, 0.09375, 0.0625, 0.015625 }, 47 | { 0.0234375, 0.09375, 0.140625, 0.09375, 0.0234375 }, 48 | { 0.015625, 0.0625, 0.09375, 0.0625, 0.015625 }, 49 | { 0.00390625, 0.015625, 0.0234375, 0.015625, 0.00390625 }, 50 | }, 51 | }; 52 | 53 | private readonly (int width, int height)[] _sizes = 54 | { 55 | (3, 3), // 0 - Matrix3x3 56 | (5, 5), // 1 - Matrix5x5 57 | }; 58 | 59 | /// 60 | /// Creates a new instance of . 61 | /// 62 | /// The Gaussian matrix to apply. 63 | public GaussianProcessor(GaussianMatrix matrix) 64 | : base() 65 | { 66 | _kernelType = (int)matrix; 67 | } 68 | 69 | /// 70 | /// Creates a new instance of . 71 | /// 72 | /// The Gaussian matrix to apply. 73 | /// The number of columns to divide the image into. 74 | /// The number of rows to divide the image into. 75 | public GaussianProcessor(GaussianMatrix matrix, int horizontalCellCount, int verticalCellCount) 76 | : base(horizontalCellCount, verticalCellCount) 77 | { 78 | _kernelType = (int)matrix; 79 | } 80 | 81 | /// 82 | public void Apply(ImageContext context) 83 | { 84 | this.ApplyConvolution(_kernels[_kernelType], _sizes[_kernelType].width, _sizes[_kernelType].height, context); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /src/MMALSharp/Native/MMALEvents.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Runtime.InteropServices; 7 | using MMALSharp.Common.Utility; 8 | 9 | namespace MMALSharp.Native 10 | { 11 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 12 | #pragma warning disable SA1132 // Each field should be declared on its own line 13 | 14 | public static class MMALEvents 15 | { 16 | public static int MMAL_EVENT_ERROR = Helpers.FourCCFromString("ERRO"); 17 | public static int MMAL_EVENT_EOS = Helpers.FourCCFromString("EEOS"); 18 | public static int MMAL_EVENT_FORMAT_CHANGED = Helpers.FourCCFromString("EFCH"); 19 | public static int MMAL_EVENT_PARAMETER_CHANGED = Helpers.FourCCFromString("EPCH"); 20 | 21 | #pragma warning disable IDE1006 // Naming Styles 22 | [DllImport("libmmal.so", EntryPoint = "mmal_event_format_changed_get", CallingConvention = CallingConvention.Cdecl)] 23 | public static extern unsafe MMAL_EVENT_FORMAT_CHANGED_T* mmal_event_format_changed_get(MMAL_BUFFER_HEADER_T* buffer); 24 | #pragma warning restore IDE1006 // Naming Styles 25 | } 26 | 27 | [StructLayout(LayoutKind.Sequential)] 28 | public struct MMAL_EVENT_END_OF_STREAM_T 29 | { 30 | private MMALPort.MMAL_PORT_TYPE_T portType; 31 | private uint portIndex; 32 | 33 | public MMALPort.MMAL_PORT_TYPE_T PortType => portType; 34 | 35 | public uint PortIndex => portIndex; 36 | 37 | public MMAL_EVENT_END_OF_STREAM_T(MMALPort.MMAL_PORT_TYPE_T portType, uint portIndex) 38 | { 39 | this.portType = portType; 40 | this.portIndex = portIndex; 41 | } 42 | } 43 | 44 | [StructLayout(LayoutKind.Sequential)] 45 | public unsafe struct MMAL_EVENT_FORMAT_CHANGED_T 46 | { 47 | private uint bufferSizeMin, bufferNumMin, bufferSizeRecommended, bufferNumRecommended; 48 | private MMAL_ES_FORMAT_T* format; 49 | 50 | public uint BufferSizeMin => bufferSizeMin; 51 | 52 | public uint BufferNumMin => bufferNumMin; 53 | 54 | public uint BufferSizeRecommended => bufferSizeRecommended; 55 | 56 | public uint BufferNumRecommended => bufferNumRecommended; 57 | 58 | public MMAL_ES_FORMAT_T* Format => format; 59 | 60 | public MMAL_EVENT_FORMAT_CHANGED_T(uint bufferSizeMin, uint bufferNumMin, uint bufferSizeRecommended, uint bufferNumRecommended, 61 | MMAL_ES_FORMAT_T* format) 62 | { 63 | this.bufferSizeMin = bufferSizeMin; 64 | this.bufferNumMin = bufferNumMin; 65 | this.bufferSizeRecommended = bufferSizeRecommended; 66 | this.bufferNumRecommended = bufferNumRecommended; 67 | this.format = format; 68 | } 69 | } 70 | 71 | [StructLayout(LayoutKind.Sequential)] 72 | public struct MMAL_EVENT_PARAMETER_CHANGED_T 73 | { 74 | public MMAL_PARAMETER_HEADER_T hdr; 75 | 76 | public MMAL_PARAMETER_HEADER_T Hdr => hdr; 77 | 78 | public MMAL_EVENT_PARAMETER_CHANGED_T(MMAL_PARAMETER_HEADER_T hdr) 79 | { 80 | this.hdr = hdr; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/ColorConversionTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System.Drawing; 7 | using MMALSharp.Common.Utility; 8 | using Xunit; 9 | 10 | namespace MMALSharp.Tests 11 | { 12 | public class ColorConversionTests 13 | { 14 | [Fact] 15 | [MMALTestsAttribute] 16 | public void FromCie1960() 17 | { 18 | var cie1960 = MMALColor.RGBToCIE1960(Color.Blue); 19 | var from1960 = MMALColor.FromCIE1960(cie1960.Item1, cie1960.Item2, cie1960.Item3); 20 | 21 | Assert.True(from1960.R == Color.Blue.R && from1960.G == Color.Blue.G && from1960.B == Color.Blue.B); 22 | } 23 | 24 | [Fact] 25 | [MMALTestsAttribute] 26 | public void FromCiexyz() 27 | { 28 | var cieXyz = MMALColor.RGBToCIEXYZ(Color.Blue); 29 | var fromXyz = MMALColor.FromCieXYZ(cieXyz.Item1, cieXyz.Item2, cieXyz.Item3); 30 | 31 | Assert.True(fromXyz.R == Color.Blue.R && fromXyz.G == Color.Blue.G && fromXyz.B == Color.Blue.B); 32 | } 33 | 34 | [Fact] 35 | [MMALTestsAttribute] 36 | public void FromYiq() 37 | { 38 | var yiq = MMALColor.RGBToYIQ(Color.Blue); 39 | var fromYiq = MMALColor.FromYIQ(yiq.Item1, yiq.Item2, yiq.Item3); 40 | 41 | Assert.True(fromYiq.R == Color.Blue.R && fromYiq.G == Color.Blue.G && fromYiq.B == Color.Blue.B); 42 | } 43 | 44 | [Fact] 45 | [MMALTestsAttribute] 46 | public void FromYuv() 47 | { 48 | var fromYuvBytes = MMALColor.FromYUVBytes(0, 20, 20); 49 | var rgbToYuv = MMALColor.RGBToYUV(fromYuvBytes); 50 | var fromYuv = MMALColor.FromYUV(rgbToYuv.Item1, rgbToYuv.Item2, rgbToYuv.Item3); 51 | 52 | Assert.True(fromYuv.Equals(fromYuvBytes)); 53 | } 54 | 55 | [Fact] 56 | [MMALTestsAttribute] 57 | public void RgbtoYuvBytes() 58 | { 59 | var yuvBytes = MMALColor.RGBToYUVBytes(Color.Blue); 60 | var fromYuvBytes = MMALColor.FromYUVBytes(yuvBytes.Item1, yuvBytes.Item2, yuvBytes.Item3); 61 | 62 | Assert.True(fromYuvBytes.R == Color.Blue.R && fromYuvBytes.G == Color.Blue.G && fromYuvBytes.B == Color.Blue.B); 63 | } 64 | 65 | [Fact] 66 | [MMALTestsAttribute] 67 | public void FromHls() 68 | { 69 | var hls = MMALColor.RGBToHLS(Color.Blue); 70 | var fromHls = MMALColor.FromHLS(hls.Item1, hls.Item2, hls.Item3); 71 | 72 | Assert.True(fromHls.R == Color.Blue.R && fromHls.G == Color.Blue.G && fromHls.B == Color.Blue.B); 73 | } 74 | 75 | [Fact] 76 | [MMALTestsAttribute] 77 | public void FromHsv() 78 | { 79 | var hsv = MMALColor.RGBToHSV(Color.Blue); 80 | var fromHsv = MMALColor.FromHSV(hsv.Item1, hsv.Item2, hsv.Item3); 81 | 82 | Assert.True(fromHsv.R == Color.Blue.R && fromHsv.G == Color.Blue.G && fromHsv.B == Color.Blue.B); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/MMALSharp.Tests/FFmpegTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using MMALSharp.Common; 10 | using MMALSharp.Components; 11 | using MMALSharp.Handlers; 12 | using MMALSharp.Native; 13 | using MMALSharp.Ports; 14 | using Xunit; 15 | 16 | namespace MMALSharp.Tests 17 | { 18 | public class FFmpegTests : TestBase 19 | { 20 | public FFmpegTests(MMALFixture fixture) 21 | : base(fixture) 22 | { 23 | } 24 | 25 | [Fact] 26 | public async Task RawVideoConvert() 27 | { 28 | TestHelper.BeginTest("RawVideoConvert"); 29 | TestHelper.SetConfigurationDefaults(); 30 | TestHelper.CleanDirectory("/home/pi/videos/tests"); 31 | 32 | using (var ffCaptureHandler = FFmpegCaptureHandler.RawVideoToAvi("/home/pi/videos/tests", "testing1234")) 33 | using (var vidEncoder = new MMALVideoEncoder()) 34 | using (var renderer = new MMALVideoRenderer()) 35 | { 36 | Fixture.MMALCamera.ConfigureCameraSettings(); 37 | 38 | var portConfig = new MMALPortConfig(MMALEncoding.H264, MMALEncoding.I420, quality: 10, bitrate: 25000000); 39 | 40 | vidEncoder.ConfigureOutputPort(portConfig, ffCaptureHandler); 41 | 42 | Fixture.MMALCamera.Camera.VideoPort.ConnectTo(vidEncoder); 43 | Fixture.MMALCamera.Camera.PreviewPort.ConnectTo(renderer); 44 | 45 | // Camera warm up time 46 | await Task.Delay(2000); 47 | 48 | var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)); 49 | 50 | // Take video for 1 minute. 51 | await Task.WhenAll(new[] 52 | { 53 | ffCaptureHandler.ProcessExternalAsync(cts.Token), 54 | Fixture.MMALCamera.ProcessAsync(Fixture.MMALCamera.Camera.VideoPort, cts.Token), 55 | }); 56 | 57 | Fixture.CheckAndAssertFilepath("/home/pi/videos/tests/testing1234.avi"); 58 | } 59 | } 60 | 61 | /*[Fact] 62 | public async Task ImagesToVideo() 63 | { 64 | TestHelper.BeginTest("ImagesToVideo"); 65 | TestHelper.SetConfigurationDefaults(); 66 | TestHelper.CleanDirectory("/home/pi/videos/tests"); 67 | TestHelper.CleanDirectory("/home/pi/images/tests"); 68 | 69 | // This example will take an image every 5 seconds for 1 minute. 70 | using (var imgCaptureHandler = new ImageStreamCaptureHandler("/home/pi/images/tests", "jpg")) 71 | { 72 | var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)); 73 | 74 | var tl = new Timelapse { Mode = TimelapseMode.Second, CancellationToken = cts.Token, Value = 5 }; 75 | await Fixture.MMALCamera.TakePictureTimelapse(imgCaptureHandler, MMALEncoding.JPEG, MMALEncoding.I420, tl); 76 | 77 | // Process all images captured into a video at 2fps. 78 | imgCaptureHandler.ImagesToVideo("/home/pi/videos/tests", 2); 79 | 80 | Fixture.CheckAndAssertFilepath("/home/pi/videos/tests/out.avi"); 81 | } 82 | }*/ 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/MMALSharp/Native/MMALPool.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace MMALSharp.Native 10 | { 11 | #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 12 | 13 | public static class MMALPool 14 | { 15 | public delegate void mmal_pool_allocator_alloc_t(IntPtr ptr, uint value); 16 | public delegate void mmal_pool_allocator_free_t(IntPtr ptr, IntPtr ptr2); 17 | 18 | // typedef - Pointer to MMAL_POOL_T struct * Pointer to MMAL_BUFFER_HEADER_T struct * Pointer to void -> Returns MMAL_BOOL_T struct 19 | public unsafe delegate int MMAL_POOL_BH_CB_T(MMAL_POOL_T* pool, MMAL_BUFFER_HEADER_T* buffer); 20 | 21 | #pragma warning disable IDE1006 // Naming Styles 22 | 23 | // MMAL_POOL_T* 24 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_create", CallingConvention = CallingConvention.Cdecl)] 25 | public static extern IntPtr mmal_pool_create(uint bufferNum, uint bufferSize); 26 | 27 | // MMAL_POOL_T* 28 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_create_with_allocator", CallingConvention = CallingConvention.Cdecl)] 29 | public static extern IntPtr mmal_pool_create_with_allocator(uint headers, 30 | uint payload_size, 31 | IntPtr allocator_context, 32 | mmal_pool_allocator_alloc_t allocator_alloc, 33 | mmal_pool_allocator_free_t allocator_free); 34 | 35 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_destroy", CallingConvention = CallingConvention.Cdecl)] 36 | public static extern unsafe void mmal_pool_destroy(MMAL_POOL_T* pool); 37 | 38 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_resize", CallingConvention = CallingConvention.Cdecl)] 39 | public static extern unsafe MMALUtil.MMAL_STATUS_T mmal_pool_resize(MMAL_POOL_T* pool, uint headers, uint payload_size); 40 | 41 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_callback_set", CallingConvention = CallingConvention.Cdecl)] 42 | public static extern unsafe void mmal_pool_callback_set(MMAL_POOL_T* pool, [MarshalAs(UnmanagedType.FunctionPtr)] MMAL_POOL_BH_CB_T cb, IntPtr userdata); 43 | 44 | [DllImport("libmmal.so", EntryPoint = "mmal_pool_pre_release_callback_set", CallingConvention = CallingConvention.Cdecl)] 45 | public static extern unsafe void mmal_pool_pre_release_callback_set(MMAL_POOL_T* pool, [MarshalAs(UnmanagedType.FunctionPtr)] MMAL_POOL_BH_CB_T cb, IntPtr userdata); 46 | #pragma warning restore IDE1006 // Naming Styles 47 | } 48 | 49 | [StructLayout(LayoutKind.Sequential)] 50 | public unsafe struct MMAL_POOL_T 51 | { 52 | private MMAL_QUEUE_T* queue; 53 | private uint headersNum; 54 | private IntPtr header; 55 | 56 | public MMAL_QUEUE_T* Queue => queue; 57 | public uint HeadersNum => headersNum; 58 | public IntPtr Header => header; 59 | 60 | public MMAL_POOL_T(MMAL_QUEUE_T* queue, uint headersNum, IntPtr header) 61 | { 62 | this.queue = queue; 63 | this.headersNum = headersNum; 64 | this.header = header; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/MMALSharp/MMALPoolImpl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using Microsoft.Extensions.Logging; 8 | using MMALSharp.Common.Utility; 9 | using MMALSharp.Native; 10 | using MMALSharp.Ports; 11 | using static MMALSharp.MMALNativeExceptionHelper; 12 | 13 | namespace MMALSharp 14 | { 15 | /// 16 | /// Represents a pool of buffer headers. An instance of this class can be created via a MMALPortImpl. 17 | /// 18 | public unsafe class MMALPoolImpl : MMALObject, IBufferPool 19 | { 20 | /// 21 | /// Native pointer that represents this buffer header pool. 22 | /// 23 | public MMAL_POOL_T* Ptr { get; } 24 | 25 | /// 26 | /// Accessor to the queue of buffer headers this pool has. 27 | /// 28 | public IBufferQueue Queue { get; } 29 | 30 | /// 31 | /// The number of buffer headers in this pool. 32 | /// 33 | public uint HeadersNum => this.Ptr->HeadersNum; 34 | 35 | /// 36 | /// Creates a new instance of based on a port. 37 | /// 38 | /// The port. 39 | public MMALPoolImpl(IPort port) 40 | { 41 | MMALLog.Logger.LogDebug($"Creating buffer pool with {port.BufferNum} buffers of size {port.BufferSize}"); 42 | 43 | this.Ptr = MMALUtil.mmal_port_pool_create(port.Ptr, port.BufferNum, port.BufferSize); 44 | this.Queue = new MMALQueueImpl((*this.Ptr).Queue); 45 | } 46 | 47 | /// 48 | /// Creates a new instance of based on an existing pointer. 49 | /// 50 | /// The pointer. 51 | public MMALPoolImpl(MMAL_POOL_T* ptr) 52 | { 53 | MMALLog.Logger.LogDebug($"Creating buffer pool from existing instance."); 54 | 55 | this.Ptr = ptr; 56 | this.Queue = new MMALQueueImpl((*this.Ptr).Queue); 57 | } 58 | 59 | /// 60 | public override bool CheckState() 61 | { 62 | return this.Ptr != null && (IntPtr)this.Ptr != IntPtr.Zero; 63 | } 64 | 65 | /// 66 | /// Resize a pool of MMAL_BUFFER_HEADER_T. This allows modifying either the number of allocated buffers, the payload size or both at the same time. 67 | /// 68 | /// Number of headers to be contained in this pool. 69 | /// The size of the headers. 70 | public void Resize(uint numHeaders, uint size) 71 | { 72 | MMALCheck(MMALPool.mmal_pool_resize(this.Ptr, numHeaders, size), "Unable to resize pool"); 73 | } 74 | 75 | /// 76 | public override void Dispose() 77 | { 78 | MMALLog.Logger.LogDebug("Disposing buffer pool."); 79 | this.Destroy(); 80 | base.Dispose(); 81 | } 82 | 83 | /// 84 | /// Destroy a pool of MMAL_BUFFER_HEADER_T. This will also deallocate all of the memory which was allocated when creating or resizing the pool. 85 | /// 86 | private void Destroy() 87 | { 88 | MMALPool.mmal_pool_destroy(this.Ptr); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/MMALSharp/Ports/Outputs/StillPort.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using Microsoft.Extensions.Logging; 8 | using MMALSharp.Common; 9 | using MMALSharp.Common.Utility; 10 | using MMALSharp.Components; 11 | using MMALSharp.Handlers; 12 | using MMALSharp.Native; 13 | using MMALSharp.Ports.Inputs; 14 | 15 | namespace MMALSharp.Ports.Outputs 16 | { 17 | /// 18 | /// Represents a still image encoder/decoder port. 19 | /// 20 | public unsafe class StillPort : OutputPort, IStillPort 21 | { 22 | private Resolution _resolution; 23 | 24 | /// 25 | public override Resolution Resolution 26 | { 27 | get 28 | { 29 | if (_resolution.Width == 0 || _resolution.Height == 0) 30 | { 31 | _resolution = new Resolution(MMALCameraConfig.Resolution.Width, MMALCameraConfig.Resolution.Height); 32 | } 33 | 34 | return _resolution; 35 | } 36 | 37 | internal set 38 | { 39 | if (value.Width == 0 || value.Height == 0) 40 | { 41 | this.NativeWidth = MMALCameraConfig.Resolution.Pad().Width; 42 | this.NativeHeight = MMALCameraConfig.Resolution.Pad().Height; 43 | _resolution = new Resolution(MMALCameraConfig.Resolution.Width, MMALCameraConfig.Resolution.Height); 44 | } 45 | else 46 | { 47 | this.NativeWidth = value.Pad().Width; 48 | this.NativeHeight = value.Pad().Height; 49 | _resolution = new Resolution(value.Width, value.Height); 50 | } 51 | } 52 | } 53 | 54 | /// 55 | /// Creates a new instance of . 56 | /// 57 | /// The native pointer. 58 | /// The component this port is associated with. 59 | /// Managed unique identifier for this component. 60 | public StillPort(IntPtr ptr, IComponent comp, Guid guid) 61 | : base(ptr, comp, guid) 62 | { 63 | } 64 | 65 | /// 66 | /// Creates a new instance of . 67 | /// 68 | /// The port to copy data from. 69 | public StillPort(IPort copyFrom) 70 | : base((IntPtr)copyFrom.Ptr, copyFrom.ComponentReference, copyFrom.Guid) 71 | { 72 | } 73 | 74 | /// 75 | public override void Configure(IMMALPortConfig config, IInputPort copyFrom, IOutputCaptureHandler handler) 76 | { 77 | base.Configure(config, copyFrom, handler); 78 | 79 | if (config != null && config.EncodingType == MMALEncoding.JPEG) 80 | { 81 | this.SetParameter(MMALParametersCamera.MMAL_PARAMETER_JPEG_Q_FACTOR, config.Quality); 82 | } 83 | } 84 | 85 | internal override void NativeOutputPortCallback(MMAL_PORT_T* port, MMAL_BUFFER_HEADER_T* buffer) 86 | { 87 | if (MMALCameraConfig.Debug) 88 | { 89 | MMALLog.Logger.LogDebug($"{this.Name}: In native {nameof(StillPort)} output callback"); 90 | } 91 | 92 | base.NativeOutputPortCallback(port, buffer); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/StreamCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using System; 7 | using System.IO; 8 | using Microsoft.Extensions.Logging; 9 | using MMALSharp.Common; 10 | using MMALSharp.Common.Utility; 11 | using MMALSharp.Processors; 12 | 13 | namespace MMALSharp.Handlers 14 | { 15 | /// 16 | /// Processes the image data to a stream. 17 | /// 18 | /// The type. 19 | public abstract class StreamCaptureHandler : OutputCaptureHandler 20 | where T : Stream 21 | { 22 | /// 23 | /// A Stream instance that we can process image data to. 24 | /// 25 | public T CurrentStream { get; protected set; } 26 | 27 | /// 28 | public override void Process(ImageContext context) 29 | { 30 | this.Processed += context.Data.Length; 31 | 32 | if (this.CurrentStream.CanWrite) 33 | this.CurrentStream.Write(context.Data, 0, context.Data.Length); 34 | else 35 | throw new IOException("Stream not writable."); 36 | 37 | base.Process(context); 38 | } 39 | 40 | /// 41 | public override void PostProcess() 42 | { 43 | try 44 | { 45 | if (this.CurrentStream != null && this.CurrentStream.CanRead && this.CurrentStream.Length > 0) 46 | { 47 | if (this.OnManipulate != null && this.ImageContext != null) 48 | { 49 | byte[] arr = null; 50 | 51 | using (var ms = new MemoryStream()) 52 | { 53 | this.CurrentStream.Position = 0; 54 | this.CurrentStream.CopyTo(ms); 55 | 56 | arr = ms.ToArray(); 57 | 58 | this.ImageContext.Data = arr; 59 | this.ImageContext.StoreFormat = this.StoreFormat; 60 | 61 | MMALLog.Logger.LogDebug("Applying image processing."); 62 | 63 | this.OnManipulate(new FrameProcessingContext(this.ImageContext)); 64 | } 65 | 66 | using (var ms = new MemoryStream(this.ImageContext.Data)) 67 | { 68 | this.CurrentStream.SetLength(0); 69 | this.CurrentStream.Position = 0; 70 | ms.CopyTo(this.CurrentStream); 71 | } 72 | } 73 | } 74 | } 75 | catch(Exception e) 76 | { 77 | MMALLog.Logger.LogWarning($"Something went wrong while processing stream: {e.Message}. {e.InnerException?.Message}. {e.StackTrace}"); 78 | } 79 | } 80 | 81 | /// 82 | public override string TotalProcessed() 83 | { 84 | return $"{Helpers.ConvertBytesToMegabytes(this.Processed)}"; 85 | } 86 | 87 | /// 88 | /// Releases the underlying stream. 89 | /// 90 | public override void Dispose() 91 | { 92 | MMALLog.Logger.LogInformation($"Successfully processed {Helpers.ConvertBytesToMegabytes(this.Processed)}."); 93 | CurrentStream?.Dispose(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/MMALSharp.Processing/Handlers/ExternalProcessCaptureHandlerOptions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Ian Auty and contributors. All rights reserved. 3 | // Licensed under the MIT License. Please see LICENSE.txt for License info. 4 | // 5 | 6 | using Mono.Unix.Native; 7 | 8 | namespace MMALSharp.Handlers 9 | { 10 | /// 11 | /// Options to pass to the constructor of . 12 | /// 13 | public class ExternalProcessCaptureHandlerOptions 14 | { 15 | /// 16 | /// In theory, ffmpeg responds to a pair of SIGINT signals with a clean shutdown, although in 17 | /// practice this doesn't appear to work when ffmpeg is running as a child process. 18 | /// 19 | public static Signum[] SignalsFFmpeg = new[] { Signum.SIGINT, Signum.SIGINT }; 20 | 21 | /// 22 | /// Clean termination signals for a VLC / cvlc process. 23 | /// 24 | public static Signum[] SignalsVLC = new[] { Signum.SIGINT }; 25 | 26 | // -------------------------------------------------------------------------------------------- 27 | // 28 | // VLC termination signals are documented here: 29 | // https://wiki.videolan.org/Hacker_Guide/Interfaces/#A_typical_VLC_run_course 30 | // 31 | // With ffmpeg realtime transcoding, the following combinations are all likely to result in 32 | // a corrupt video file (for example, MP4 encoding will be missing the end-header MOOV atom). 33 | // Testing also shows it doesn't help to delay between sending the signals. 34 | // 35 | // Termination signal combos tested include SIGINT followed by: 36 | // SIGINT, SIGABRT, SIGALRM, SIGBUS, SIGTERM, SIGHUP - immediate stop, no output of any kind 37 | // SIGQUIT - ouputs a message, tries to write trailer (MOOV atom), aborts 38 | // 39 | // Certain simpler video formats like AVI may either complete successfully, or at least play 40 | // without obvious issues but they are still likely to be "technically" corrupted at the end. 41 | // 42 | // -------------------------------------------------------------------------------------------- 43 | 44 | /// 45 | /// The name of the process to be launched (e.g. ffmpeg, cvlc, etc.) 46 | /// 47 | public string Filename = string.Empty; 48 | 49 | /// 50 | /// Command line arguments used to start the process. 51 | /// 52 | public string Arguments = string.Empty; 53 | 54 | /// 55 | /// When true, stdout and stderr data is asynchronously buffered and output. When false, output is 56 | /// completely suppressed, which may improve release-build performance. If true and MMAL is also 57 | /// configured for logging, process output will also be logged. 58 | /// 59 | public bool EchoOutput = true; 60 | 61 | /// 62 | /// When the token is canceled, 63 | /// a short delay will ensure any final output from the process is echoed. Ignored if EchoOutput is 64 | /// false. This delay occurs after any TerminationSignals are issued. 65 | /// 66 | public int DrainOutputDelayMs = 500; 67 | 68 | /// 69 | /// If present, when the token is 70 | /// canceled, these signals will be sent to the process. Some processes expect a CTRL+C (SIGINT). 71 | /// 72 | public Signum[] TerminationSignals = new Signum[] { }; 73 | } 74 | } 75 | --------------------------------------------------------------------------------