In-Daemon Filter System
Background
Sensor Framework already has a filter sytem sits in sensor API library (in-library), that means, applications play with sensor of same type may have multi instances of a same filter in their process space. For example, applicaiton A applies Kalman filter to its accelerometer dataflow, application B does same thing, then there will be two filter pipelines in memory, one is in A's process space, another in B's process space. An usual solution is moving filter system into sensor daemon, that's why I worte the in-daemon filter system.
Highlights
Comparing the old in-library filter system, new system has below advantages:
Self contained. New system only depends on sensor framework itself. The orignal one depends on GStreamer.
Effective. Given that orignal filter pipeline is driven by GStreamer, the new filter pipeline works in a more effective way.
Easy to use. There are only three essential filter APIs for driver module, so it's quite easy to use.
Easy to write a filter. The orignal filter system requires filter author implements both filter itself and an GStreamer element, in a way, it's diffcult. New system just requires filter plug-in itself.
Easy to configure. Driver moudle could configure perferred filters in configure file (module.conf)
Write a Filter
It's very similar with writing a driver modue, but easier. Filter is required to provide three functions:
/**
* SFFilterObjInit:
* @fobj: a #SFFilterObj
*
* Initalization function of filter pulgin. This function
* called when a filter plug-in is loaded. Filter
* should do initalization in this function.
*
* Returns: 0 for success or -1 for fail
*/
typedef gint (*SFFilterObjInit) (SFFilterObj* fobj);
/**
* SFFilterObjExit:
* @fobj: a #SFFilterObj
*
* Exit function of filter pulgin. This function called
* when a filter pulg-in is unloaded. Filter should do
* clean up including free memory allocated by itself in this
* function.
*/
typedef void (*SFFilterObjExit) (SFFilterObj* fobj);
/**
* SFFilterObjRun:
* @fobj: a #SFFilterObj
* @data: data need be filtered
*
* This function called by drvier module to filter @data.
* Filter should implement its logic in this function. The format
* of @data is decided by sensor type that filter serves. For example,
* #FAccelFrame is format of accelerometer. All data formats should be
* defined in src/core/filter.h. @data passed in is the raw data, before
* the function return, filter should store filtered result in @data.
*/
typedef void (*SFFilterObjRun) (SFFilterObj* fobj, gpointer data);#SFFilterObj has below definition:
/**
* _SFFilterObj:
* @name: name of filter
* @type: sensor type the filter serves
* @run: filter implementation function
* @priv: Use to store filter's private data
*/
struct _SFFilterObj {
GModule* gmodule;
gchar* name;
SFSensorType type;
gint ref;
SFFilterObjInit init;
SFFilterObjRun run;
SFFilterObjExit exit;
gpointer priv;
};Please treate these non-comment fileds as readonly. @name filed must be evaluated by a macro FILTER_NAME, or the filter may not be recognised. @type is the sensor type, for filter serves accelerometer, the type must be TYPE_ACCEL, otherwise the filter will not be loaded.
Below is a sample copied from accel-avg-filter.c
int filter__init (SFFilterObj* fobj) {
fobj->priv = priv_new ();
fobj->run = run;
fobj->type = TYPE_ACCEL;
fobj->name = FILTER_NAME;
return 0;
}src/core/filter-modules/accel-avg-filter.c is a sample filter for reference, please see in code for details.
Like driver module, you have to modify Makefile.am to produce an auto-generated header file.
For example.
FILTER_SYMDEF_FILES = \
core/filter-modules/accel-avg-filter-symdef.hThe *-symdef.h header file must be included in C file of filer.
Name convention
For the C file of filter, please use below name convention:
<sensor name>-<filter name>-filter.c
E.g. accel-avg-filter.c, accel-lowpass-filter.c
Filter API for driver module
User is allowed to configure perferred filter in "filters" filed of module.conf. For instance:
[module-accel-simulator]
x-path = accel_x
y-path = accel_y
z-path = accel_z
sample-interval = 20
signature = I am signature of module-accel-simulator
filters = accel-avg-filter;accel-lowpass-filter;
Multi filters are separated by semicolon.
Driver module could parse filter list using:
/**
* sf_parse_filter_list:
* @m: A #SFModule
*
* Parse filter list from configure file
*
* Returns: A string list ended with a NULL entry
*/
gchar** sf_parse_filter_list (SFModule* m);Usually, filter pipeline is constructed in initialization function sf__init() using:
/**
* sf_sensordev_create_filter_pipeline:
* @c: A #SFCore
* @dev: A #SFSensorDev
* @args: a varying number of arguments of char*, ended with NULL
*
* Construct filter pipeline using filter specified by name in varying
* arguments.
*
* For example:
* sf_sensordev_create_filter_pipeline (c, dev, "accel-avg-filter", NULL);
* Returns: 0 means success. -1 indicates there is one or more filter load
* failed.
*/
gint sf_sensordev_create_filter_pipeline (SFCore* c, SFSensorDev* dev, ...)or
/**
* sf_sensordev_create_filter_pipeline_2:
* @c: A #SFCore
* @dev: A #SFSensorDev
* @names: A filter name list, ended with NULL
*
* Construct filter pipeline using filter specified in @names
*
* Returns: 0 means success. -1 indicates there is one or more filter load
* failed.
*/
gint sf_sensordev_create_filter_pipeline_2 (SFCore* c, SFSensorDev* dev, gchar** names)or a more convenient way:
/**
* sf_construct_pipeline_from_filter_list:
* @m: A #SFModule
* @dev: A #SFSensorDev
*
* Parse filter list from configure file and construct filter pipeline
*
* Returns: 0 means success or no filter configured. -1 means one or more
* filter load failed
*/
gint sf_construct_pipeline_from_filter_list (SFModule* m, SFSensorDev* dev)To destroy a pipeline, call:
/**
* sf_sensordev_destory_filter_pipeline:
* @c: A #SFCore
* @dev: A #SFSensorDev
*
* Distory filter pipeline
*/
void sf_sensordev_destory_filter_pipeline (SFCore* c, SFSensorDev* dev)To filter raw data, call
/**
* sf_sensordev_filter_run:
* @dev: A #SFSensorDev
* @data: data need to be filterd
*
* Filter @data using filter pipeline of @dev. Format of data is
* defined in src/core/filter.h. For accelerometer, its #FAccelFrame.
*
* Pass raw data in @data, when the function returns, @data contain
* the filtered result
*/
void sf_sensordev_filter_run (SFSensorDev* dev, gpointer data)Samples
src/core/filter-modules/accel-avg-filter.c: A simple average FIR filter
src/modules/module-accel-simulator.c: Driver module using average FIR filter
- Printer-friendly version
- Login or register to post comments