From b38f8e84c4153ce90dea47da42f65a3c5f9b9568 Mon Sep 17 00:00:00 2001 From: c0ntrol Date: Sun, 20 Mar 2016 19:34:15 +0100 Subject: [PATCH] add livido fx background subtraction --- .../veejay-server/livido-plugins/Makefile.am | 8 +- .../livido-plugins/lvd_bgsubtract.c | 239 ++++++++++++++++++ 2 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 veejay-current/veejay-server/livido-plugins/lvd_bgsubtract.c diff --git a/veejay-current/veejay-server/livido-plugins/Makefile.am b/veejay-current/veejay-server/livido-plugins/Makefile.am index 8cdf7a29..594af633 100644 --- a/veejay-current/veejay-server/livido-plugins/Makefile.am +++ b/veejay-current/veejay-server/livido-plugins/Makefile.am @@ -1,17 +1,19 @@ -lividoplugin_LTLIBRARIES = lvd_solid.la \ +lividoplugin_LTLIBRARIES = lvd_bgsubtract.la \ + lvd_solid.la \ lvd_colortone.la \ lvd_displaywall.la \ lvd_stroboscope.la \ lvd_colorexchange.la +lvd_bgsubtract_la_SOURCES = lvd_bgsubtract.c lvd_solid_la_SOURCES = lvd_solid.c lvd_colortone_la_SOURCES = lvd_colortone.c lvd_displaywall_la_SOURCES = lvd_displaywall.c lvd_stroboscope_la_SOURCES = lvd_stroboscope.c lvd_colorexchange_la_SOURCES = lvd_colorexchange.c -AM_CPPFLAGS = $(FFMPEG_CFLAGS) -AM_CFLAGS = -I@top_srcdir@/include $(OP_CFLAGS) +AM_CPPFLAGS = $(FFMPEG_CFLAGS) $(VJE_CFLAGS) +AM_CFLAGS = -I@top_srcdir@/include $(VJE_CFLAGS) AM_LDFLAGS = -module -avoid-version -lm -export-dynamic AM_LIBTOOLFLAGS = --tag=disable-static diff --git a/veejay-current/veejay-server/livido-plugins/lvd_bgsubtract.c b/veejay-current/veejay-server/livido-plugins/lvd_bgsubtract.c new file mode 100644 index 00000000..d976090a --- /dev/null +++ b/veejay-current/veejay-server/livido-plugins/lvd_bgsubtract.c @@ -0,0 +1,239 @@ +/* + * LIBVJE - veejay fx library + * + * Copyright(C)2016 Niels Elburg + * See COPYING for software license and distribution details + */ + +#ifndef IS_LIVIDO_PLUGIN +#define IS_LIVIDO_PLUGIN +#endif + +#include "../libplugger/specs/livido.h" +LIVIDO_PLUGIN +#include "utils.h" +#include "livido-utils.c" + +#include "lvd_common.h" + +#define RUP8(num)(((num)+8)&~8) + +typedef struct +{ + uint8_t *bg; + int frame_no; +} bgsubtract_t; + +livido_init_f init_instance( livido_port_t *my_instance ) +{ + int w = 0, h = 0; + lvd_extract_dimensions( my_instance, "out_channels", &w, &h ); + + bgsubtract_t *b = (bgsubtract_t*) livido_malloc(sizeof(bgsubtract_t)); + b->bg = (uint8_t*) livido_malloc( sizeof(uint8_t) * RUP8(w * h) ); + + livido_property_set( my_instance, "PLUGIN_private", LIVIDO_ATOM_TYPE_VOIDPTR,1, &b); + + livido_memset( b->bg, 0, w * h ); + + return LIVIDO_NO_ERROR; +} + + +livido_deinit_f deinit_instance( livido_port_t *my_instance ) +{ + void *ptr = NULL; + if ( livido_property_get( my_instance, "PLUGIN_private", 0, &ptr ) == LIVIDO_NO_ERROR ) + { + bgsubtract_t *b = (bgsubtract_t*) ptr; + if( b->bg ) { + livido_free( b->bg ); + } + livido_free(b); + } + + return LIVIDO_NO_ERROR; +} + +void lvd_vje_diff_plane( uint8_t *__restrict__ A, uint8_t *__restrict__ B, uint8_t *__restrict__ O, int threshold, const int len ) +{ + unsigned int i; + for( i = 0; i < len; i ++ ) { + O[i] = abs( A[i] - B[i] ); + if( O[i] < threshold ) + O[i] = 0; + else + O[i] = 0xff; + } +} + +void lvd_avg_frame( uint8_t *__restrict__ A, uint8_t *__restrict__ O, const int len ) +{ + unsigned int i; + for( i = 0; i < len; i ++ ) + { + O[i] = (O[i] + A[i]) >> 1; + } +} + +int process_instance( livido_port_t *my_instance, double timecode ) +{ + int len =0; + uint8_t *A[4] = {NULL,NULL,NULL,NULL}; + uint8_t *O[4]= {NULL,NULL,NULL,NULL}; + int palette; + int w; + int h; + bgsubtract_t *ptr = NULL; + + int error = lvd_extract_channel_values( my_instance, "out_channels", 0, &w,&h, O,&palette ); + if( error != LIVIDO_NO_ERROR ) + return LIVIDO_ERROR_NO_OUTPUT_CHANNELS; + + error = lvd_extract_channel_values( my_instance, "in_channels" , 0, &w, &h, A, &palette ); + if( error != LIVIDO_NO_ERROR ) + return LIVIDO_ERROR_NO_INPUT_CHANNELS; + + error = livido_property_get( my_instance, "PLUGIN_private", 0, &ptr ); + if( error != LIVIDO_NO_ERROR ) + return LIVIDO_ERROR_INTERNAL; + + int uv_len = lvd_uv_plane_len( palette,w,h ); + len = w * h; + + int snap_bg = lvd_extract_param_index( my_instance,"in_parameters", 0 ); + int threshold = lvd_extract_param_index( my_instance,"in_parameters", 1 ); + int mode = lvd_extract_param_index( my_instance,"in_parameters", 2 ); + + if( snap_bg ) { + if( ptr->frame_no == 0 ) { + livido_memcpy( ptr->bg, A[0], len ); + } + else { + /* average frames (assumes that background is static) */ + lvd_avg_frame( A[0], ptr->bg, len ); + } + ptr->frame_no ++; + + /* while snapping, show bg frame */ + livido_memcpy( O[0], ptr->bg, len ); + livido_memset( O[1], 128, uv_len ); + livido_memset( O[2], 128, uv_len ); + } + else { + if( mode == 0 ) { + lvd_vje_diff_plane( ptr->bg, A[0], O[0], threshold, len ); + livido_memset( O[1], 128, uv_len ); + livido_memset( O[2], 128, uv_len ); + } + else { + lvd_vje_diff_plane( ptr->bg, A[0], O[3], threshold, len ); + } + + ptr->frame_no = 0; + } + + return LIVIDO_NO_ERROR; +} + +livido_port_t *livido_setup(livido_setup_t list[], int version) + +{ + LIVIDO_IMPORT(list); + + livido_port_t *port = NULL; + livido_port_t *in_params[3]; + livido_port_t *in_chans[3]; + livido_port_t *out_chans[1]; + livido_port_t *info = NULL; + livido_port_t *filter = NULL; + + //@ setup root node, plugin info + info = livido_port_new( LIVIDO_PORT_TYPE_PLUGIN_INFO ); + port = info; + + livido_set_string_value( port, "maintainer", "Niels"); + livido_set_string_value( port, "version","1"); + + filter = livido_port_new( LIVIDO_PORT_TYPE_FILTER_CLASS ); + livido_set_int_value( filter, "api_version", LIVIDO_API_VERSION ); + + //@ setup function pointers + livido_set_voidptr_value( filter, "deinit_func", &deinit_instance ); + livido_set_voidptr_value( filter, "init_func", &init_instance ); + livido_set_voidptr_value( filter, "process_func", &process_instance ); + port = filter; + + //@ meta information + livido_set_string_value( port, "name", "Background Subtraction"); + livido_set_string_value( port, "description", "Subtract the background"); + livido_set_string_value( port, "author", "Niels Elburg"); //ported to livido + + livido_set_int_value( port, "flags", 0); + livido_set_string_value( port, "license", "GPL2"); + livido_set_int_value( port, "version", 1); + + //@ some palettes veejay-classic uses + int palettes0[] = { + LIVIDO_PALETTE_YUV422P, + LIVIDO_PALETTE_YUV444P, + 0, + }; + + //@ setup output channel + out_chans[0] = livido_port_new( LIVIDO_PORT_TYPE_CHANNEL_TEMPLATE ); + port = out_chans[0]; + + livido_set_string_value( port, "name", "Output Channel"); + livido_set_int_array( port, "palette_list", 3, palettes0); + livido_set_int_value( port, "flags", 0); + + in_chans[0] = livido_port_new( LIVIDO_PORT_TYPE_CHANNEL_TEMPLATE ); + port = in_chans[0]; + livido_set_string_value( port, "name", "Input Channel"); + livido_set_int_array( port, "palette_list", 3, palettes0); + livido_set_int_value( port, "flags", 0); + + //@ setup parameters (INDEX type, 0-255) + in_params[0] = livido_port_new( LIVIDO_PORT_TYPE_PARAMETER_TEMPLATE ); + port = in_params[0]; + + livido_set_string_value(port, "name", "Background" ); + livido_set_string_value(port, "kind", "INDEX" ); + livido_set_int_value( port, "min", 0 ); + livido_set_int_value( port, "max", 1 ); + livido_set_int_value( port, "default", 0 ); + livido_set_string_value( port, "description" ,"Set to snap current frame as a background frame"); + + + in_params[1] = livido_port_new( LIVIDO_PORT_TYPE_PARAMETER_TEMPLATE ); + port = in_params[1]; + + livido_set_string_value(port, "name", "Threshold" ); + livido_set_string_value(port, "kind", "INDEX" ); + livido_set_int_value( port, "min", 0 ); + livido_set_int_value( port, "max", 255 ); + livido_set_int_value( port, "default", 40 ); + livido_set_string_value( port, "description" ,"Difference Threshold"); + + + + in_params[2] = livido_port_new( LIVIDO_PORT_TYPE_PARAMETER_TEMPLATE ); + port = in_params[2]; + + livido_set_string_value(port, "name", "Alpha" ); + livido_set_string_value(port, "kind", "INDEX" ); + livido_set_int_value( port, "min", 0); + livido_set_int_value( port, "max", 1 ); + livido_set_int_value( port, "default", 0 ); + livido_set_string_value( port, "description" ,"Set difference frame as Alpha Channel"); + + + //@ setup the nodes + livido_set_portptr_array( filter, "in_parameter_templates",3, in_params ); + livido_set_portptr_array( filter, "out_channel_templates", 1, out_chans ); + livido_set_portptr_array( filter, "in_channel_templates",1, in_chans ); + + livido_set_portptr_value(info, "filters", filter); + return info; +}