From 1e62476374ac1b7226a61f42e6312ff97fbdf3da Mon Sep 17 00:00:00 2001 From: c0ntrol Date: Sun, 20 Mar 2016 19:36:11 +0100 Subject: [PATCH] fix bg subtract, add extra mode to magic mirror, fix snap bg, added special mode to magic mirror that depends on bg subtraction --- .../veejay-server/libvje/effects/bgsubtract.c | 141 +++++++------- .../veejay-server/libvje/effects/bgsubtract.h | 3 +- .../veejay-server/libvje/effects/common.c | 6 +- .../libvje/effects/magicmirror.c | 174 +++++++++++++----- .../libvje/effects/magicmirror.h | 3 +- .../veejay-server/libvje/effects/motionmap.c | 142 +++++++++----- .../veejay-server/libvje/effects/motionmap.h | 10 +- .../veejay-server/libvje/internal.h | 8 +- .../veejay-server/libvje/vj-effman.c | 18 +- veejay-current/veejay-server/libvje/vje.h | 1 + veejay-current/veejay-server/veejay/vj-misc.c | 47 +---- veejay-current/veejay-server/veejay/vj-misc.h | 2 +- .../veejay-server/veejay/vj-perform.c | 47 +++-- 13 files changed, 378 insertions(+), 224 deletions(-) diff --git a/veejay-current/veejay-server/libvje/effects/bgsubtract.c b/veejay-current/veejay-server/libvje/effects/bgsubtract.c index f9cb8100..55023fff 100644 --- a/veejay-current/veejay-server/libvje/effects/bgsubtract.c +++ b/veejay-current/veejay-server/libvje/effects/bgsubtract.c @@ -26,110 +26,125 @@ #include #include #include "softblur.h" -static uint8_t *static_bg = NULL; +#include + +static uint8_t *static_bg__ = NULL; +static uint8_t *bg_frame__[4] = { NULL,NULL,NULL,NULL }; +static int bg_ssm = 0; vj_effect *bgsubtract_init(int width, int height) { - vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); - ve->num_params = 3; - ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ - ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ - ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ - ve->limits[0][0] = 0; /* threshold */ - ve->limits[1][0] = 255; - ve->limits[0][1] = 0; /* mode */ - ve->limits[1][1] = 1; + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; /* threshold */ + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* mode */ + ve->limits[1][1] = 1; ve->limits[0][2] = 0; /* alpha */ - ve->limits[1][2] = 1; + ve->limits[1][2] = 1; - ve->defaults[0] = 45; - ve->defaults[1] = 0; + ve->defaults[0] = 45; + ve->defaults[1] = 1; ve->defaults[2] = 0; - ve->description = "Substract background (static, requires bg mask)"; - ve->extra_frame = 0; - ve->sub_format = -1; - ve->has_user = 1; - ve->user_data = NULL; + ve->description = "Subtract background"; + ve->extra_frame = 0; + ve->sub_format = -1; + ve->has_user = 1; + ve->user_data = NULL; ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Mode", "To Alpha"); ve->hints = vje_init_value_hint_list( ve->num_params ); - vje_build_value_hint_list( ve->hints, ve->limits[1][1], 1,"Preview", "Inverted preview", "Normal" ); + vje_build_value_hint_list( ve->hints, ve->limits[1][1], 1,"Show Difference", "Show Static BG" ); ve->alpha = FLAG_ALPHA_OUT | FLAG_ALPHA_OPTIONAL; - return ve; + return ve; } -#define rup8(num)(((num)+8)&~8) int bgsubtract_malloc(int width, int height) { - if(static_bg == NULL) - static_bg = (uint8_t*) vj_calloc( rup8( width + width * height * sizeof(uint8_t)) ); + if(static_bg__ == NULL){ + static_bg__ = (uint8_t*) vj_malloc( RUP8(width*height)*4); + bg_frame__[0] = static_bg__; + bg_frame__[1] = bg_frame__[0] + RUP8(width*height); + bg_frame__[2] = bg_frame__[1] + RUP8(width*height); + bg_frame__[3] = bg_frame__[2] + RUP8(width*height); + } + return 1; } void bgsubtract_free() { - if( static_bg ) - free(static_bg ); - static_bg = NULL; + if( static_bg__ ) { + free(static_bg__ ); + + bg_frame__[0] = NULL; + bg_frame__[1] = NULL; + bg_frame__[2] = NULL; + bg_frame__[3] = NULL; + static_bg__ = NULL; + } } -int bgsubtract_prepare(uint8_t *map[4], int width, int height) +int bgsubtract_prepare(VJFrame *frame) { - if(!static_bg ) + if(!static_bg__ ) { return 0; } //@ copy the iamge - veejay_memcpy( static_bg, map[0], (width*height)); + veejay_memcpy( bg_frame__[0], frame->data[0], frame->len ); + if( frame->ssm ) { + veejay_memcpy( bg_frame__[1], frame->data[1], frame->len ); + veejay_memcpy( bg_frame__[2], frame->data[2], frame->len ); + } + else { + // if data is subsampled, super sample it now + veejay_memcpy( bg_frame__[1], frame->data[1], frame->uv_len ); + veejay_memcpy( bg_frame__[2], frame->data[2], frame->uv_len ); + chroma_supersample( SSM_422_444, frame, bg_frame__ ); + } + + bg_ssm = 1; - VJFrame tmp; - veejay_memset( &tmp, 0, sizeof(VJFrame)); - tmp.data[0] = static_bg; - tmp.width = width; - tmp.height = height; - - //@ 3x3 blur - softblur_apply( &tmp, width,height,0); - - veejay_msg(2, "Substract background: Snapped background frame"); + veejay_msg(2, "Subtract background: Snapped background frame"); return 1; } +uint8_t* bgsubtract_get_bg_frame(unsigned int plane) +{ + return bg_frame__[ plane ]; +} + void bgsubtract_apply(VJFrame *frame,int width, int height, int threshold, int mode, int alpha ) { - VJFrame tmp; - veejay_memset( &tmp, 0, sizeof(VJFrame)); - tmp.data[0] = frame->data[0]; - tmp.width = width; - tmp.height = height; + const int uv_len = (frame->ssm ? frame->len : frame->uv_len ); - //@ 3x3 blur - softblur_apply( &tmp, width,height,0); + if( mode ) { + veejay_memcpy( frame->data[0], bg_frame__[0], frame->len ); + if( frame->ssm ) { + veejay_memcpy( frame->data[1], bg_frame__[1], frame->len ); + veejay_memcpy( frame->data[2], bg_frame__[2], frame->len ); + } else { /* if chain is still subsampled, copy only greyscale image */ + veejay_memset( frame->data[1], 128, frame->uv_len ); + veejay_memset( frame->data[2], 128, frame->uv_len ); + } + return; + } if( alpha == 0 ) { - if ( mode == 0 ) { - binarify( frame->data[0], static_bg,frame->data[0], threshold, 0, width*height ); - } else if ( mode == 1 ) { - binarify( frame->data[0], static_bg, frame->data[0], threshold, 1,width*height ); - } - - veejay_memset( frame->data[1], 128, frame->uv_len ); - veejay_memset( frame->data[2], 128, frame->uv_len ); + veejay_memset( frame->data[1], 128, uv_len ); + veejay_memset( frame->data[2], 128, uv_len ); + vje_diff_plane( bg_frame__[0], frame->data[0], frame->data[0], threshold, frame->len ); } else { - if ( mode == 0 ) { - binarify( frame->data[0], static_bg,frame->data[3], threshold, 0, width*height ); - } else if ( mode == 1 ) { - binarify( frame->data[0], static_bg, frame->data[3], threshold, 1,width*height ); - } + vje_diff_plane( bg_frame__[0], frame->data[0], frame->data[3], threshold, frame->len ); } } - - - - diff --git a/veejay-current/veejay-server/libvje/effects/bgsubtract.h b/veejay-current/veejay-server/libvje/effects/bgsubtract.h index 0e93a15b..5490e85f 100644 --- a/veejay-current/veejay-server/libvje/effects/bgsubtract.h +++ b/veejay-current/veejay-server/libvje/effects/bgsubtract.h @@ -27,6 +27,7 @@ vj_effect *bgsubtract_init(int width, int height); void bgsubtract_free(); int bgsubtract_malloc(int w, int h); -int bgsubtract_prepare(uint8_t *map[4], int w, int h); +int bgsubtract_prepare(VJFrame *frame); void bgsubtract_apply(VJFrame *frame,int width,int height,int mode, int threshold, int to_alpha); +uint8_t *bgsubtract_get_bg_frame(unsigned int plane); #endif diff --git a/veejay-current/veejay-server/libvje/effects/common.c b/veejay-current/veejay-server/libvje/effects/common.c index 93873dc8..7ab033b8 100644 --- a/veejay-current/veejay-server/libvje/effects/common.c +++ b/veejay-current/veejay-server/libvje/effects/common.c @@ -1490,7 +1490,11 @@ void vje_diff_plane( uint8_t *A, uint8_t *B, uint8_t *O, int threshold, int len { unsigned int i; for( i = 0; i < len; i ++ ) { - O[i] = ( abs( B[i] - A[i] ) > threshold ? 0xff : 0 ); + O[i] = abs( A[i] - B[i] ); + if( O[i] < threshold ) + O[i] = 0; + else + O[i] = 0xff; } } diff --git a/veejay-current/veejay-server/libvje/effects/magicmirror.c b/veejay-current/veejay-server/libvje/effects/magicmirror.c index 9c6adbb4..f6c141fc 100644 --- a/veejay-current/veejay-server/libvje/effects/magicmirror.c +++ b/veejay-current/veejay-server/libvje/effects/magicmirror.c @@ -1,7 +1,7 @@ /* * Linux VeeJay * - * Copyright(C)2004 Niels Elburg + * Copyright(C)2004-2016 Niels Elburg * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +23,8 @@ #include #include "magicmirror.h" #include "common.h" +#include "motionmap.h" +#include // if d or n changes, tables need to be calculated static uint8_t *magicmirrorbuf[4] = { NULL,NULL,NULL,NULL }; @@ -31,47 +33,60 @@ static double *funhouse_y = NULL; static unsigned int *cache_x = NULL; static unsigned int *cache_y = NULL; static unsigned int last[4] = {0,0,20,20}; +static int cx1 = 0; +static int cx2 = 0; static int n__ = 0; static int N__ = 0; vj_effect *magicmirror_init(int w, int h) { - vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); - ve->num_params = 4; - ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ - ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ - ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ - ve->defaults[0] = w/4; - ve->defaults[1] = h/4; - ve->defaults[2] = 20; - ve->defaults[3] = 20; + ve->defaults[0] = w/4; + ve->defaults[1] = h/4; + ve->defaults[2] = 20; + ve->defaults[3] = 20; + ve->defaults[4] = 0; + + ve->limits[0][0] = 0; + ve->limits[1][0] = w/2; + ve->limits[0][1] = 0; + ve->limits[1][1] = h/2; + ve->limits[0][2] = 0; + ve->limits[1][2] = 100; + ve->limits[0][3] = 0; + ve->limits[1][3] = 100; + ve->limits[0][4] = 0; + ve->limits[1][4] = 2; - ve->limits[0][0] = 0; - ve->limits[1][0] = w/2; - ve->limits[0][1] = 0; - ve->limits[1][1] = h/2; - ve->limits[0][2] = 0; - ve->limits[1][2] = 100; - ve->limits[0][3] = 0; - ve->limits[1][3] = 100; ve->motion = 1; - ve->sub_format = 1; - ve->description = "Magic Mirror Surface"; + ve->sub_format = 1; + ve->description = "Magic Mirror Surface"; ve->has_user =0; - ve->extra_frame = 0; - ve->param_description = vje_build_param_list(ve->num_params, "X", "Y", "X","Y" ); - return ve; + ve->extra_frame = 0; + ve->alpha = FLAG_ALPHA_SRC_A | FLAG_ALPHA_OUT | FLAG_ALPHA_OPTIONAL; + ve->param_description = vje_build_param_list(ve->num_params, "X", "Y", "X","Y", "Alpha" ); + + ve->hints = vje_init_value_hint_list( ve->num_params ); + + vje_build_value_hint_list( ve->hints, ve->limits[1][4], 4, "Normal", "Alpha Mirror Mask", "Alpha Mirror Mask Only" ); + + return ve; } int magicmirror_malloc(int w, int h) { - magicmirrorbuf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t)*RUP8(w*h*3)); + magicmirrorbuf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t)*RUP8(w*h*4)); if(!magicmirrorbuf[0]) return 0; magicmirrorbuf[1] = magicmirrorbuf[0] + RUP8(w*h); magicmirrorbuf[2] = magicmirrorbuf[1] + RUP8(w*h); + magicmirrorbuf[3] = magicmirrorbuf[2] + RUP8(w*h); funhouse_x = (double*)vj_calloc(sizeof(double) * w ); if(!funhouse_x) return 0; @@ -101,13 +116,14 @@ void magicmirror_free() magicmirrorbuf[0] = NULL; magicmirrorbuf[1] = NULL; magicmirrorbuf[2] = NULL; + magicmirrorbuf[3] = NULL; cache_x = NULL; cache_y = NULL; funhouse_x = NULL; funhouse_y = NULL; } -void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int n ) +void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int n, int alpha ) { double c1 = (double)vx; double c2 = (double)vy; @@ -115,7 +131,14 @@ void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int int interpolate = 1; if( motionmap_active()) { - motionmap_scale_to( 100,100,0,0, &d, &n, &n__, &N__ ); + if( motionmap_is_locked() ) { + d = cx1; + n = cx2; + } else { + motionmap_scale_to( 100,100,0,0, &d, &n, &n__, &N__ ); + cx1 = d; + cx2 = n; + } motion = 1; } else @@ -134,6 +157,7 @@ void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int uint8_t *Y = frame->data[0]; uint8_t *Cb= frame->data[1]; uint8_t *Cr= frame->data[2]; + uint8_t *A = frame->data[3]; if( d != last[1] ) { changed = 1; last[1] =d; @@ -165,14 +189,6 @@ void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int funhouse_y[y] = res; } } - -// int strides[4] = { len,len,len, 0 }; -// vj_frame_copy( frame->data, magicmirrorbuf, strides ); - - veejay_memcpy( magicmirrorbuf[0], frame->data[0], len ); - veejay_memcpy( magicmirrorbuf[1], frame->data[1], len ); - veejay_memcpy( magicmirrorbuf[2], frame->data[2], len ); - for(x=0; x < w; x++) { dx = x + funhouse_x[x] * c1; @@ -188,17 +204,91 @@ void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int cache_y[y] = dy; } - for(y=1; y < h-1; y++) - { - for(x=1; x < w-1; x++) + veejay_memcpy( magicmirrorbuf[0], frame->data[0], len ); + veejay_memcpy( magicmirrorbuf[1], frame->data[1], len ); + veejay_memcpy( magicmirrorbuf[2], frame->data[2], len ); + + if( alpha ) { + veejay_memcpy( magicmirrorbuf[3], frame->data[3], len ); + /* apply on alpha first */ + for(y=1; y < h-1; y++) { - p = cache_y[y] * w + cache_x[x]; - q = y * w + x; - Y[q] = magicmirrorbuf[0][p]; - Cb[q] = magicmirrorbuf[1][p]; - Cr[q] = magicmirrorbuf[2][p]; + for(x=1; x < w-1; x++) + { + q = y * w + x; + p = cache_y[y] * w + cache_x[x]; + A[q] = magicmirrorbuf[3][p]; + } + } + + uint8_t *Am = magicmirrorbuf[3]; + + switch(alpha) { + case 1: + for(y=1; y < h-1; y++) + { + for(x=1; x < w-1; x++) + { + q = y * w + x; + p = cache_y[y] * w + cache_x[x]; + if( Am[p] || A[q] ) { + Y[q] = magicmirrorbuf[0][p]; + Cb[q] = magicmirrorbuf[1][p]; + Cr[q] = magicmirrorbuf[2][p]; + } + } + } + break; + case 2: + { + //@ try get a bg from somwhere + uint8_t *bgY = vj_effect_get_bg( VJ_IMAGE_EFFECT_BGSUBTRACT, 0 ); + uint8_t *bgCb= vj_effect_get_bg( VJ_IMAGE_EFFECT_BGSUBTRACT, 1 ); + uint8_t *bgCr= vj_effect_get_bg( VJ_IMAGE_EFFECT_BGSUBTRACT, 2 ); + + if( bgY == NULL || bgCb == NULL || bgCr == NULL ) { + veejay_msg(0,"This mode requires 'Subtract background' FX"); + break; + } + for(y=1; y < h-1; y++) + { + for(x=1; x < w-1; x++) + { + q = y * w + x; + p = cache_y[y] * w + cache_x[x]; + + if( A[q] ) { + Y[q] = magicmirrorbuf[0][p]; + Cb[q] = magicmirrorbuf[1][p]; + Cr[q] = magicmirrorbuf[2][p]; + } else if ( Am[q] ) { + //@ put in pixels from static bg + Y[q] = bgY[q]; + Cb[q] = bgCb[q]; + Cr[q] = bgCr[q]; + } + } + } + + } + break; } } + else { + for(y=1; y < h-1; y++) + { + for(x=1; x < w-1; x++) + { + q = y * w + x; + p = cache_y[y] * w + cache_x[x]; + + Y[q] = magicmirrorbuf[0][p]; + Cb[q] = magicmirrorbuf[1][p]; + Cr[q] = magicmirrorbuf[2][p]; + } + } + } + if( interpolate ) { diff --git a/veejay-current/veejay-server/libvje/effects/magicmirror.h b/veejay-current/veejay-server/libvje/effects/magicmirror.h index dde65fba..a1072d79 100644 --- a/veejay-current/veejay-server/libvje/effects/magicmirror.h +++ b/veejay-current/veejay-server/libvje/effects/magicmirror.h @@ -27,7 +27,6 @@ vj_effect *magicmirror_init(int w, int h); int magicmirror_malloc(int w, int h); -void magicmirror_apply( VJFrame *frame, int width, int height, int a, int b, - int na, int nb); +void magicmirror_apply( VJFrame *frame, int width, int height, int a, int b, int na, int nb, int alpha); void magicmirror_free(); #endif diff --git a/veejay-current/veejay-server/libvje/effects/motionmap.c b/veejay-current/veejay-server/libvje/effects/motionmap.c index 05ec129e..d3531ef4 100644 --- a/veejay-current/veejay-server/libvje/effects/motionmap.c +++ b/veejay-current/veejay-server/libvje/effects/motionmap.c @@ -32,6 +32,16 @@ * To use the plain C version, define NO_AUTOVECTORIZATION */ +/* TODO: + * + * + * create mask of foreground object (aproximate IR) + * put mask into alpha-channel + * apply secundary effect on alpha-channel + * apply secundary effect on whole frame, using alpha channel + * + */ + #include #include #include @@ -49,7 +59,7 @@ vj_effect *motionmap_init(int w, int h) { vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); - ve->num_params = 6; + ve->num_params = 7; ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ @@ -66,19 +76,28 @@ vj_effect *motionmap_init(int w, int h) ve->limits[1][3] = HIS_LEN; ve->limits[0][5] = 0; ve->limits[1][5] = 1; + ve->limits[0][6] = 0; + ve->limits[1][6] = 3; ve->defaults[0] = 40; ve->defaults[1] = 1000; ve->defaults[2] = 1; ve->defaults[3] = HIS_DEFAULT; ve->defaults[4] = HIS_DEFAULT; ve->defaults[5] = 0; + ve->defaults[6] = 0; ve->description = "Motion Mapping"; ve->sub_format = 1; ve->extra_frame = 0; ve->has_user = 0; ve->n_out = 2; - ve->param_description = vje_build_param_list( ve->num_params, - "Difference Threshold", "Maximum Motion Energy","Draw Motion Map","History in frames" ,"Decay", "Interpolate frames"); +// ve->alpha = FLAG_ALPHA_OUT | FLAG_ALPHA_SRC_A; + ve->param_description = vje_build_param_list( ve->num_params, + "Difference Threshold", "Maximum Motion Energy","Draw Motion Map","History in frames" ,"Decay", "Interpolate frames", "Activity Mode"); + + ve->hints = vje_init_value_hint_list( ve->num_params ); + + vje_build_value_hint_list( ve->hints, ve->limits[1][6], 6, "Normal", "Local Max", "Global Max", "Hold Last" ); + return ve; } @@ -91,6 +110,7 @@ static uint8_t *prev_img = NULL; static uint8_t *interpolate_buf = NULL; static int32_t max = 0; +static int32_t global_max = 0; static uint32_t nframe_ =0; static int current_his_len = HIS_DEFAULT; static int current_decay = HIS_DEFAULT; @@ -100,6 +120,7 @@ static int running = 0; static int is_initialized = 0; static int do_interpolation = 0; static int stored_frame = 0; +static int scale_lock = 0; int motionmap_malloc(int w, int h ) { @@ -148,6 +169,9 @@ void motionmap_free(void) do_interpolation = 0; keyv_ = 0; keyp_ = 0; + scale_lock = 0; + global_max = 0; + stored_frame = 0; binary_img = NULL; prev_img = NULL; } @@ -167,6 +191,11 @@ int motionmap_active() return running; } +int motionmap_is_locked() +{ + return scale_lock; +} + uint32_t motionmap_activity() { return keyv_; @@ -174,24 +203,24 @@ uint32_t motionmap_activity() void motionmap_scale_to( int p1max, int p2max, int p1min, int p2min, int *p1val, int *p2val, int *pos, int *len ) { - if( max == 0 ) + if( global_max == 0 || scale_lock ) return; - if( keyv_ > max ) + if( keyv_ > global_max ) { - keyv_ = max; + keyv_ = global_max; } int n = (nframe_ % current_decay) + 1; float q = 1.0f / (float) current_decay * n; float diff = (float) keyv_ - (float) keyp_ ; float pu = keyp_ + (q * diff); - float m = (float) max; + float m = (float) global_max; if( pu > m ) pu = m; - float w = 1.0 / max; + float w = 1.0 / global_max; float pw = w * pu; *p1val = p1min + (int) ((p1max-p1min) * pw); @@ -290,7 +319,6 @@ void motionmap_calc_diff( const uint8_t *bg, uint8_t *prev_img, const uint8_t *i unsigned int i; uint8_t p1,p2; -#ifndef NO_AUTOVECTORIZATION uint8_t *I1 = pI1; uint8_t *I2 = pI2; @@ -308,6 +336,7 @@ void motionmap_calc_diff( const uint8_t *bg, uint8_t *prev_img, const uint8_t *i else I2[i] = 0xff; +// A[i] = I1[i]; I1[i] = abs( I1[i] - I2[i] ); I2[i] = bDst[i] >> 1; } @@ -317,30 +346,6 @@ void motionmap_calc_diff( const uint8_t *bg, uint8_t *prev_img, const uint8_t *i bDst[i] = I1[i] + I2[i]; prev_img[i] = img[i]; } -#else - for( i = 0; i < len; i ++ ) - { - uint8_t q1 = 0, q2 = 0; - p1 = abs( bg[i] - img[i] ); - if( p1 > threshold ) { - q1 = 1; - } - - p2 = abs( bg[i] - prev_img[i] ); - if( p2 > threshold ) { - q2 = 1; - } - - if( (!q1 && q2) || (!q2 && q1) ) { - bDst[i] = 0xff; - } - else { - bDst[i] = (bDst[i] >> 1); //@ decay - } - - prev_img[i] = img[i]; - } -#endif } void motionmap_find_diff_job( void *arg ) @@ -350,6 +355,7 @@ void motionmap_find_diff_job( void *arg ) const uint8_t *t_bg = t->input[0]; const uint8_t *t_img = t->input[1]; uint8_t *t_prev_img = t->input[2]; +// uint8_t *t_alpha = t->input[3]; uint8_t *t_binary_img = t->output[0]; uint8_t *t_diff1 = t->output[1]; uint8_t *t_diff2 = t->output[2]; @@ -357,7 +363,8 @@ void motionmap_find_diff_job( void *arg ) const int len = t->strides[0]; const int threshold = t->iparams[0]; - motionmap_calc_diff( t_bg, t_prev_img, t_img,t_diff1,t_diff2, t_binary_img, len, threshold ); +// motionmap_calc_diff( t_bg, t_prev_img, t_img,t_diff1,t_diff2, t_binary_img,t_alpha, len, threshold ); + motionmap_calc_diff( t_bg, t_prev_img, t_img,t_diff1,t_diff2, t_binary_img,len, threshold ); } int motionmap_prepare( uint8_t *map[4], int width, int height ) @@ -374,16 +381,20 @@ int motionmap_prepare( uint8_t *map[4], int width, int height ) running = 0; stored_frame = 0; do_interpolation = 0; + scale_lock = 0; veejay_msg(2, "Motion Mapping: Snapped background frame"); return 1; } +static int32_t global_act = 0; -void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int limit, int draw, int history, int decay, int interpol ) +void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int limit, int draw, int history, int decay, int interpol, int last_act_level ) { unsigned int i; const unsigned int len = (width * height); uint8_t *Cb = frame->data[1]; uint8_t *Cr = frame->data[2]; +// uint8_t *alpha = frame->data[3]; + if(!have_bg) { veejay_msg(VEEJAY_MSG_ERROR,"Motion Mapping: Snap the background frame with VIMS 339 or mask button in reloaded"); return; @@ -395,10 +406,12 @@ void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int task.stride[0] = len; // plane length task.stride[1] = len; task.stride[2] = len; + // task.stride[3] = len; task.stride[3] = 0; task.data[0] = bg_image; // plane 0 = background image task.data[1] = frame->data[0]; // plane 1 = luminance channel task.data[2] = prev_img; // plane 2 = luminance channel of previous frame + // task.data[3] = alpha; task.data[3] = NULL; task.ssm = 1; // all planes are the same size task.format = frame->format; // not important, but cannot be 0 @@ -409,15 +422,19 @@ void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int task.width = width; // dimensions task.height = height; + // uint8_t *dst[4] = { binary_img, diff_img, diff_img + RUP8(len), alpha }; uint8_t *dst[4] = { binary_img, diff_img, diff_img + RUP8(len), NULL }; + vj_task_set_from_frame( &task ); vj_task_set_param( threshold, 0 ); - vj_task_run( task.data, dst, NULL,NULL,3, (performer_job_routine) &motionmap_find_diff_job ); + vj_task_run( task.data, dst, NULL,NULL,4, (performer_job_routine) &motionmap_find_diff_job ); } else { + // motionmap_calc_diff( (const uint8_t*) bg_image, prev_img, (const uint8_t*) frame->data[0], diff_img, diff_img + RUP8(len), binary_img, alpha, len, threshold ); motionmap_calc_diff( (const uint8_t*) bg_image, prev_img, (const uint8_t*) frame->data[0], diff_img, diff_img + RUP8(len), binary_img, len, threshold ); + } if( draw ) @@ -427,12 +444,15 @@ void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int vj_frame_copy1( binary_img, frame->data[0], len ); running = 0; stored_frame = 0; + scale_lock = 0; return; } int32_t activity_level = motionmap_activity_level( binary_img, width, height ); int32_t avg_actlvl = 0; int32_t min = INT_MAX; + int32_t local_max = 0; + current_his_len = history; current_decay = decay; @@ -444,21 +464,55 @@ void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int avg_actlvl += histogram_[i]; if(histogram_[i] > max ) max = histogram_[i]; if(histogram_[i] < min ) min = histogram_[i]; + if(histogram_[i] > local_max) local_max = histogram_[i]; } avg_actlvl = avg_actlvl / current_his_len; - - if( avg_actlvl < limit ) + if( avg_actlvl < limit ) { avg_actlvl = 0; + } nframe_ ++; - if( (nframe_ % current_his_len)==0 ) - { - key1_ = min; - key2_ = max; - keyp_ = keyv_; - keyv_ = avg_actlvl; + switch( last_act_level ) { + case 0: + if( (nframe_ % current_his_len)==0 ) + { + key1_ = min; + key2_ = max; + keyp_ = keyv_; + keyv_ = avg_actlvl; + global_max = max; + } + break; + case 1: + key1_ = min; + key2_ = max; + keyv_ = local_max; + global_max = local_max; + break; + case 2: + key1_ = min; + key2_ = max; + keyp_ = keyv_; + keyv_ = avg_actlvl; + global_max = max; + break; + case 3: + if( (nframe_ % current_his_len)==0 ) + { + key1_ = min; + key2_ = max; + keyp_ = keyv_; + keyv_ = avg_actlvl; + global_max = max; + } + + if( avg_actlvl == 0 ) + scale_lock = 1; + else + scale_lock = 0; + break; } running = 1; diff --git a/veejay-current/veejay-server/libvje/effects/motionmap.h b/veejay-current/veejay-server/libvje/effects/motionmap.h index 9e50ccf2..87f7473c 100644 --- a/veejay-current/veejay-server/libvje/effects/motionmap.h +++ b/veejay-current/veejay-server/libvje/effects/motionmap.h @@ -25,8 +25,14 @@ #include vj_effect *motionmap_init(int w, int h); -void motionmap_apply( VJFrame *frame, int width, int height, int t, int n, int draw, int histo, int op, int ip); +void motionmap_apply( VJFrame *frame, int width, int height, int t, int n, int draw, int histo, int op, int ip, int la); int motionmap_malloc(int w,int h); void motionmap_free(void); -int motionmap_prepare( uint8_t *map[4], int w, int h ); +int motionmap_prepare( uint8_t *map[4], int w, int h ); +int motionmap_active(); +int motionmap_is_locked(); +uint8_t *motionmap_interpolate_buffer(); +uint8_t *motionmap_bgmap(); +void motionmap_store_frame( VJFrame *fx ); +void motionmap_interpolate_frame( VJFrame *fx, int N, int n ); #endif diff --git a/veejay-current/veejay-server/libvje/internal.h b/veejay-current/veejay-server/libvje/internal.h index 3d4f65ea..faf02c82 100644 --- a/veejay-current/veejay-server/libvje/internal.h +++ b/veejay-current/veejay-server/libvje/internal.h @@ -512,7 +512,7 @@ extern void pencilsketch_apply(VJFrame *frame, int w, int h, int type, int thres extern void pixelate_apply(VJFrame *frame, int w, int h, int v ); -extern void magicmirror_apply(VJFrame *frame, int w, int h, int x, int y, int d, int n ); +extern void magicmirror_apply(VJFrame *frame, int w, int h, int x, int y, int d, int n, int alpha ); extern void lumamask_apply(VJFrame *frame,VJFrame *frame2, int w, int h, int n, int m, int border, int alpha); @@ -539,7 +539,9 @@ extern void dissolve_apply(VJFrame *frame,VJFrame *frame2, int w, int h, int opa extern void overclock_apply(VJFrame *frame, int w, int h, int val, int r); -extern int bgsubtract_prepare(uint8_t *map[4], int w, int h); +uint8_t *bgsubtract_get_bg_frame(unsigned int plane); + +extern int bgsubtract_prepare(VJFrame *frame); extern void bgsubtract_apply(VJFrame *frame,int width, int height, int mode, int threshold, int alpha ); @@ -585,7 +587,7 @@ extern void picinpic_apply( void *user_data, VJFrame *frame, VJFrame *frame2, extern void threshold_apply( VJFrame *frame, VJFrame *frame2,int width, int height, int threshold, int reverse ); -extern void motionmap_apply( VJFrame *frame, int w, int h, int threshold, int reverse, int draw, int his, int op, int ip ); +extern void motionmap_apply( VJFrame *frame, int w, int h, int threshold, int reverse, int draw, int his, int op, int ip, int la ); extern void rgbchannel_apply( VJFrame *frame, int width, int height, int chr, int chg , int chb); diff --git a/veejay-current/veejay-server/libvje/vj-effman.c b/veejay-current/veejay-server/libvje/vj-effman.c index c391c6c3..ade8d9e6 100644 --- a/veejay-current/veejay-server/libvje/vj-effman.c +++ b/veejay-current/veejay-server/libvje/vj-effman.c @@ -208,7 +208,7 @@ void vj_effman_apply_image_effect( arg[1]); break; case VJ_IMAGE_EFFECT_MAGICMIRROR: - magicmirror_apply(frames[0],frames[0]->width,frames[0]->height,arg[0],arg[1],arg[2],arg[3]); + magicmirror_apply(frames[0],frames[0]->width,frames[0]->height,arg[0],arg[1],arg[2],arg[3],arg[4]); break; case VJ_IMAGE_EFFECT_RASTER: raster_apply(frames[0],frames[0]->width,frames[0]->height,arg[0],arg[1]); @@ -391,7 +391,7 @@ void vj_effman_apply_image_effect( deinterlace_apply( frames[0], frames[0]->width, frames[0]->height, arg[0]); break; case VJ_IMAGE_EFFECT_MOTIONMAP: - motionmap_apply( frames[0], frames[0]->width,frames[0]->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); + motionmap_apply( frames[0], frames[0]->width,frames[0]->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); break; case VJ_IMAGE_EFFECT_CONTOUR: contourextract_apply( vj_effects[entry]->user_data, frames[0], @@ -708,6 +708,18 @@ void vj_effman_apply_video_effect( VJFrame **frames, vjp_kf *todo_info,int *arg, } } +uint8_t* vj_effect_get_bg( int selector, unsigned int plane ) +{ + switch( selector ) { + case VJ_IMAGE_EFFECT_BGSUBTRACT: + return bgsubtract_get_bg_frame( plane ); + break; + default: + break; + } + return NULL; +} + int vj_effect_prepare( VJFrame *frame, int selector) { int fx_id = vj_effect_real_to_sequence( selector ); @@ -716,7 +728,7 @@ int vj_effect_prepare( VJFrame *frame, int selector) switch( selector ) { case VJ_IMAGE_EFFECT_BGSUBTRACT: - return bgsubtract_prepare( frame->data, frame->width,frame->height ); + return bgsubtract_prepare( frame ); break; case VJ_IMAGE_EFFECT_CONTOUR: return contourextract_prepare(frame->data,frame->width,frame->height ); diff --git a/veejay-current/veejay-server/libvje/vje.h b/veejay-current/veejay-server/libvje/vje.h index 9da4f7d9..c5864f93 100644 --- a/veejay-current/veejay-server/libvje/vje.h +++ b/veejay-current/veejay-server/libvje/vje.h @@ -133,6 +133,7 @@ extern int vj_effect_initialized(int e, void *ptr); extern int vj_effect_get_by_name(char *name); extern int vj_effect_apply( VJFrame **frames, VJFrameInfo *frameinfo, vjp_kf *kf, int selector, int *arguments, void *ptr); extern int vj_effect_prepare( VJFrame *frame, int selector); +extern uint8_t *vj_effect_get_bg( int selector, unsigned int plane ); extern void vj_effect_dump(void); extern int rgb_parameter_conversion_type_; extern int vj_effect_is_plugin( int fx_id ); diff --git a/veejay-current/veejay-server/veejay/vj-misc.c b/veejay-current/veejay-server/veejay/vj-misc.c index d42f17ce..b7ff39d8 100644 --- a/veejay-current/veejay-server/veejay/vj-misc.c +++ b/veejay-current/veejay-server/veejay/vj-misc.c @@ -219,44 +219,17 @@ filelist_t *find_media_files( veejay_t *info ) } -int vj_perform_take_bg(veejay_t *info, VJFrame *frame, int pass) +int vj_perform_take_bg(veejay_t *info, VJFrame *frame) { - int n = 0; - if( pass == 0 ) { - if(frame->ssm == 1 ) { - n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_CHAMBLEND ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CHAMELEON ); - if(n > 0 ) - return 1; - } - if(frame->ssm == 0) { - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); - n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_MOTIONMAP ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); - if( n > 0 ) - return 1; - } - - if( frame->ssm == 0 ) - { - chroma_supersample( info->settings->sample_mode,frame,frame->data ); - n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_CHAMBLEND ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CHAMELEON ); - frame->ssm = 1; - return 0; - } - - return (n > 0 ? 0: 1 ); - } else { - if(frame->ssm == 0) { - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); - n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_MOTIONMAP ); - n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); - return 0; - } - } + vj_effect_prepare( frame, VJ_VIDEO_EFFECT_CHAMBLEND ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CHAMELEON ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); + vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_MOTIONMAP ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); + vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); + vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); return 0; } diff --git a/veejay-current/veejay-server/veejay/vj-misc.h b/veejay-current/veejay-server/veejay/vj-misc.h index e5700c25..9a2883f4 100644 --- a/veejay-current/veejay-server/veejay/vj-misc.h +++ b/veejay-current/veejay-server/veejay/vj-misc.h @@ -53,7 +53,7 @@ long vj_get_relative_time(void); void vj_stamp_clear(); unsigned int vj_stamp(); -int vj_perform_take_bg( veejay_t *info, VJFrame *src, int pass); +int vj_perform_take_bg( veejay_t *info, VJFrame *src); int veejay_create_temp_file(const char *prefix, char *dst); diff --git a/veejay-current/veejay-server/veejay/vj-perform.c b/veejay-current/veejay-server/veejay/vj-perform.c index 6ef9fec1..8b2b7d1f 100644 --- a/veejay-current/veejay-server/veejay/vj-perform.c +++ b/veejay-current/veejay-server/veejay/vj-perform.c @@ -2645,8 +2645,13 @@ static void vj_perform_plain_fill_buffer(veejay_t * info, int *ret) *ret = vj_perform_get_frame_(info, info->uc->sample_id, settings->current_frame_num,&frame,&frame, p0_buffer,p1_buffer,0 ); } else if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_PLAIN ) { *ret = vj_perform_get_frame_(info, 0, settings->current_frame_num,&frame,&frame, p0_buffer, p1_buffer,0 ); - } + + if(info->uc->take_bg==1 ) + { + info->uc->take_bg = vj_perform_take_bg(info,&frame); + } + } static int rec_audio_sample_ = 0; static int vj_perform_render_sample_frame(veejay_t *info, uint8_t *frame[4], int sample) @@ -2958,19 +2963,17 @@ static int vj_perform_tag_fill_buffer(veejay_t * info) if(!active) { - if (type == VJ_TAG_TYPE_V4L || type == VJ_TAG_TYPE_NET || type == VJ_TAG_TYPE_MCAST || type == VJ_TAG_TYPE_PICTURE ) - vj_tag_enable( info->uc->sample_id ); - } + if (type == VJ_TAG_TYPE_V4L || type == VJ_TAG_TYPE_NET || type == VJ_TAG_TYPE_MCAST || type == VJ_TAG_TYPE_PICTURE ) + vj_tag_enable( info->uc->sample_id ); + } else { - - if (vj_tag_get_frame(info->uc->sample_id, info->effect_frame1,NULL)) - { - error = 0; - cached_tag_frames[0] = info->uc->sample_id; - } - - } + if (vj_tag_get_frame(info->uc->sample_id, info->effect_frame1,NULL)) + { + error = 0; + cached_tag_frames[0] = info->uc->sample_id; + } + } if (error == 1) { @@ -2983,7 +2986,13 @@ static int vj_perform_tag_fill_buffer(veejay_t * info) dumb.data[3] = frame[3]; dummy_apply(&dumb,info->video_output_width,info->video_output_height,VJ_EFFECT_COLOR_BLACK ); } - return 1; + + if(info->uc->take_bg==1 ) + { + info->uc->take_bg = vj_perform_take_bg(info,info->effect_frame1); + } + + return 1; } static void vj_perform_pre_chain(veejay_t *info, VJFrame *frame) @@ -3531,11 +3540,6 @@ static void vj_perform_finish_render( veejay_t *info, video_playback_setup *sett free(more_text); - if (info->uc->take_bg==1) - { - info->uc->take_bg = vj_perform_take_bg(info,frame,0); - } - if(!settings->composite && info->uc->mouse[0] > 0 && info->uc->mouse[1] > 0) { if( info->uc->mouse[2] == 1 ) { @@ -3609,7 +3613,6 @@ static void vj_perform_finish_render( veejay_t *info, video_playback_setup *sett } } - if( frame->ssm == 1 ) { chroma_subsample(settings->sample_mode,frame,pri); @@ -3621,12 +3624,6 @@ static void vj_perform_finish_render( veejay_t *info, video_playback_setup *sett frame2->ssm=0; } - if (info->uc->take_bg==1) - { - vj_perform_take_bg(info,frame,1); - info->uc->take_bg = 0; - } - if( frame2->data[0] == frame->data[0] ) frame->ssm = 0; }