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

Handling data in MMALSharp

Ian Auty edited this page May 16, 2020 · 1 revision

When you begin using MMALSharp you will want to familiarise yourself with the ways in which you can handle data with the library. MMALSharp introduces two ways in which you can interact with the data produced by the Raspberry Pi camera and the native MMAL library, namely Capture Handlers and Callback Handlers.

Capture Handlers

I will begin by introducing you to what are known as Capture Handlers as these are the most common data handling types you will come across when using MMALSharp. Capture Handlers are classes which either feed user provided data into a component or store data produced by the components in your pipeline.

You assign Capture Handlers for use with a port using the ConfigureInputPort and ConfigureOutputPort methods against an IInputPort or IOutputPort instance. Once a handler has been assigned to a port it becomes a "Processing Port" and MMALSharp will know to either feed from or store data to it. We will now discuss Input and Ouput Capture Handlers in more detail below.

Input Capture Handlers

Capture Handlers which feed data into components implement the IInputCaptureHandler interface and will typically be used when you have a source file which you would like to run through an encoder or decoder component. In such a scenario, your data is fed into MMAL buffer headers and into the input port you have configured to use your Capture Handler with. From here, each connected component in your pipeline will interact with the data you're feeding in.

Output Capture Handlers

These data handling types are the most common you'll come across in MMALSharp as the output handlers are typically responsible for storing the final data produced by the components. Output Capture Handlers implement the IOutputCaptureHandler interface and expose a Process method which is called by the library each time a MMAL buffer is returned on a output port. This Process method is then passed a ImageContext object which contains, but not limited to: a byte array containing the frame data and whether this data represents the end of a frame.

Callback Handlers

Callback Handlers were added to the library to abstract the managed operations away from the native callback functions. Each time a buffer is returned to a processing port's native callback function the registered Callback Handler is then called to carry out additional logic which may be required. Input and Output Callback Handlers are the objects which in turn contain a reference to the Capture Handlers, therefore it is your responsibility to handle that interaction if you decide to register your own implementation.

As a user of MMALSharp, registering your own custom Callback Handler could be useful if you want to gain access to the additional properties exposed by the IBuffer instance passed to it via the Callback method.

Callback Handlers currently implement one of the following interfaces: IInputCallbackHandler, IOutputCallbackHandler or IConnectionCallbackHandler and as their names suggest, are used with either Input and Output port callbacks or Connections.

In order to register your own callback handler use the relevant RegisterCallbackHandler method(s) against a IInputPort, IOutputPort or IConnection instance.

Note: When registering your own Callback Handler for Ports it is important to do this after calling the ConfigureInputPort/ConfigureOutputPort methods because these themselves register a default Callback Handler for the port and would override your registration.

Connection Callback Handlers

Connection Callback Handlers come into play when creating connections between your components and setting useCallback to true when calling the ConnectTo method on a IOutputPort instance. When this parameter is set, the NativeConnectionCallback method in the MMALConnectionImpl class which represents the connection between two components will be called when MMAL buffers are passed between them. This functionality has a caveat though: performance. Enabling this should be considered advanced functionality and should only be used when you want to carry out debugging of buffer headers between components. This facility is disabled by default.