add new boxblur plugin, mods to videoscope, fix segv for menu btns kfrm-tweak/kfrm...
authorGood Guy <[email protected]>
Tue, 31 Mar 2020 03:46:33 +0000 (21:46 -0600)
committerGood Guy <[email protected]>
Tue, 31 Mar 2020 03:46:33 +0000 (21:46 -0600)
15 files changed:
cinelerra-5.1/cinelerra/Makefile
cinelerra-5.1/cinelerra/boxblur.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/boxblur.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/boxblur.inc [new file with mode: 0644]
cinelerra-5.1/cinelerra/editpanel.C
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/scopewindow.C
cinelerra-5.1/cinelerra/scopewindow.h
cinelerra-5.1/cinelerra/scopewindow.inc
cinelerra-5.1/cinelerra/theme.C
cinelerra-5.1/info/plugins.txt
cinelerra-5.1/msg/txt
cinelerra-5.1/plugins/Makefile
cinelerra-5.1/plugins/boxblur/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/boxblur/boxblur.C [new file with mode: 0644]

index 59a0e82c7f2f777060fda39c5e9ee9dd84d1251b..81d1aceefd0027e05de04267e48fe738a7a2b6a2 100644 (file)
@@ -79,6 +79,7 @@ OBJS := $(OVERLAYS) \
        $(OBJDIR)/bdcreate.o \
        $(OBJDIR)/binfolder.o \
        $(OBJDIR)/bitspopup.o \
+       $(OBJDIR)/boxblur.o \
        $(OBJDIR)/brender.o \
        $(OBJDIR)/browsebutton.o \
        $(OBJDIR)/byteorderpopup.o \
diff --git a/cinelerra-5.1/cinelerra/boxblur.C b/cinelerra-5.1/cinelerra/boxblur.C
new file mode 100644 (file)
index 0000000..07d7d67
--- /dev/null
@@ -0,0 +1,210 @@
+#include "boxblur.h"
+// from ffmpeg vf_boxblur
+
+template<class dst_t, class src_t> static inline
+void blurt(dst_t *dst, int dst_step, src_t *src, int src_step,
+               int len, int radius, float s)
+{
+       const int length = radius*2 + 1;
+       const int inv = s * ((1<<16) + length/2)/length;
+       int x, n, sum = src[radius*src_step];
+
+       for( x=0; x<radius; ++x )
+               sum += src[x*src_step]<<1;
+       sum = sum*inv + (1<<15);
+       for( x=0; x<=radius; ++x ) {
+               sum += (src[(radius+x)*src_step] - src[(radius-x)*src_step])*inv;
+               dst[x*dst_step] = sum>>16;
+       }
+       n = len - radius;
+       for( ; x<n; ++x ) {
+               sum += (src[(radius+x)*src_step] - src[(x-radius-1)*src_step])*inv;
+               dst[x*dst_step] = sum >>16;
+       }
+       for ( ; x<len; ++x ) {
+               sum += (src[(2*len-radius-x-1)*src_step] - src[(x-radius-1)*src_step])*inv;
+               dst[x*dst_step] = sum>>16;
+       }
+}
+// specialize const float *src
+template<class dst_t> static inline
+void blurt(dst_t *dst, int dst_step, const float *src, int src_step,
+               int len, int radius, float s)
+{
+       const float length = radius*2 + 1;
+       const float inv = s / length;
+       int x, n;
+       float sum = src[radius*src_step];
+       for( x=0; x<radius; ++x )
+               sum += src[x*src_step]*2;
+       sum = sum*inv;
+       for( x=0; x<=radius; ++x ) {
+               sum += (src[(radius+x)*src_step] - src[(radius-x)*src_step])*inv;
+               dst[x*dst_step] = sum;
+       }
+       n = len - radius;
+       for( ; x<n; ++x ) {
+               sum += (src[(radius+x)*src_step] - src[(x-radius-1)*src_step])*inv;
+               dst[x*dst_step] = sum;
+       }
+       for ( ; x<len; ++x ) {
+               sum += (src[(2*len-radius-x-1)*src_step] - src[(x-radius-1)*src_step])*inv;
+               dst[x*dst_step] = sum;
+       }
+}
+
+// s scales dst=src first pass
+template<class dst_t, class src_t> static inline
+void blur_power(dst_t *dst, int dst_step, src_t *src, int src_step,
+               int len, int radius, int power, float s)
+{
+       dst_t atemp[len], btemp[len];
+       dst_t *a = atemp, *b = btemp;
+       blurt(a, 1, src, src_step, len, radius, s);
+       while( power-- > 2 ) {
+               blurt(b, 1, (const dst_t*)a, 1, len, radius, 1);
+               dst_t *t = a; a = b; b = t;
+       }
+       if( power > 1 )
+               blurt(dst, dst_step, (const dst_t*)a, 1, len, radius, 1);
+       else
+               for( int i = 0; i<len; ++i ) dst[i*dst_step] = a[i];
+}
+
+
+BoxBlurPackage::BoxBlurPackage()
+ : LoadPackage()
+{
+}
+
+BoxBlurUnit::BoxBlurUnit(BoxBlur *box_blur)
+ : LoadClient(box_blur)
+{
+}
+
+template<class dst_t, class src_t>
+void BoxBlurUnit::blurt_package(LoadPackage *package)
+{
+       BoxBlur *box_blur = (BoxBlur *)server;
+       src_t *src_data = (src_t *)box_blur->src_data;
+       dst_t *dst_data = (dst_t *)box_blur->dst_data;
+       int radius = box_blur->radius;
+       int power = box_blur->power;
+       int vlen = box_blur->vlen;
+       int c0 = box_blur->c0, c1 = box_blur->c1;
+       int src_ustep = box_blur->src_ustep;
+       int dst_ustep = box_blur->dst_ustep;
+       int src_vstep = box_blur->src_vstep;
+       int dst_vstep = box_blur->dst_vstep;
+       BoxBlurPackage *pkg = (BoxBlurPackage*)package;
+       int u1 = pkg->u1, u2 = pkg->u2;
+       float s = 1.;
+       if( sizeof(src_t) != sizeof(dst_t) ) {
+               switch( sizeof(dst_t) ) {
+               case 1: s = sizeof(src_t)==2 ? 1/256. : 255.;  break;
+               case 2: s = sizeof(src_t)==1 ?   256. : 65535.;  break;
+               case 4: s = sizeof(src_t)==1 ? 1/256. : 1/65535.;  break;
+               }
+       }
+       for( int u=u1; u<u2; ++u ) {
+               src_t *sp = src_data + u*src_ustep;
+               dst_t *dp = dst_data + u*dst_ustep;
+               for( int c=c0; c<=c1; ++c ) {
+                       blur_power(dp+c, dst_vstep, sp+c, src_vstep,
+                               vlen, radius, power, s);
+               }
+       }
+}
+
+void BoxBlurUnit::process_package(LoadPackage *package)
+{
+       BoxBlur *box_blur = (BoxBlur *)server;
+       int src_bpp = box_blur->src_bpp, dst_bpp = box_blur->dst_bpp;
+       switch( src_bpp ) {
+       case 1: switch( dst_bpp ) {
+               case 1: blurt_package<uint8_t,  const uint8_t>(package);  break;
+               case 2: blurt_package<uint16_t, const uint8_t>(package);  break;
+               case 4: blurt_package<float,    const uint8_t>(package);  break;
+               }
+               break;
+       case 2: switch( dst_bpp ) {
+               case 1: blurt_package<uint8_t,  const uint16_t>(package); break;
+               case 2: blurt_package<uint16_t, const uint16_t>(package); break;
+               case 4: blurt_package<float,    const uint16_t>(package); break;
+               }
+               break;
+       case 4: switch( dst_bpp ) {
+               case 1: blurt_package<uint8_t,  const float>(package);    break;
+               case 2: blurt_package<uint16_t, const float>(package);    break;
+               case 4: blurt_package<float,    const float>(package);    break;
+               }
+               break;
+       }
+}
+
+BoxBlur::BoxBlur(int cpus)
+ : LoadServer(cpus, cpus)
+{
+}
+BoxBlur::~BoxBlur()
+{
+}
+
+LoadClient* BoxBlur::new_client() { return new BoxBlurUnit(this); }
+LoadPackage* BoxBlur::new_package() { return new BoxBlurPackage(); }
+
+void BoxBlur::init_packages()
+{
+       int u = 0;
+       for( int i=0,n=LoadServer::get_total_packages(); i<n; ) {
+               BoxBlurPackage *pkg = (BoxBlurPackage*)get_package(i);
+               pkg->u1 = u;
+               pkg->u2 = u = (++i * ulen) / n;
+       }
+}
+
+//dst can equal src, requires geom(dst)==geom(src)
+//uv: 0=hblur, 1=vblur;  comp: -1=rgb,0=r,1=g,2=b
+void BoxBlur::process(VFrame *dst, VFrame *src, int uv,
+               int radius, int power, int comp)
+{
+       this->radius = radius;
+       this->power = power;
+       this->uv = uv;
+       int src_w = src->get_w(), src_h = src->get_h();
+       ulen = !uv ? src_h : src_w;
+       vlen = !uv ? src_w : src_h;
+       c0 = comp<0 ? 0 : comp;
+       c1 = comp<0 ? 2 : comp;
+       src_data = src->get_data();
+       dst_data = dst->get_data();
+       int src_pixsz = BC_CModels::calculate_pixelsize(src->get_color_model());
+       int src_comps = BC_CModels::components(src->get_color_model());
+       src_bpp = src_pixsz / src_comps;
+       int dst_pixsz = BC_CModels::calculate_pixelsize(dst->get_color_model());
+       int dst_comps = BC_CModels::components(dst->get_color_model());
+       dst_bpp = dst_pixsz / dst_comps;
+       int dst_linsz = dst->get_bytes_per_line() / dst_bpp;
+       int src_linsz = src->get_bytes_per_line() / src_bpp;
+       src_ustep = !uv ? src_linsz : src_comps;
+       dst_ustep = !uv ? dst_linsz: dst_comps;
+       src_vstep = !uv ? src_comps : src_linsz;
+       dst_vstep = !uv ? dst_comps : dst_linsz;
+
+       process_packages();
+}
+
+void BoxBlur::hblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+       process(dst, src, 0, radius, power, comp);
+}
+void BoxBlur::vblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+       process(dst, src, 1, radius, power, comp);
+}
+void BoxBlur::blur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+       process(dst, src, 0, radius, power, comp);
+       process(dst, dst, 1, radius, power, comp);
+}
+
diff --git a/cinelerra-5.1/cinelerra/boxblur.h b/cinelerra-5.1/cinelerra/boxblur.h
new file mode 100644 (file)
index 0000000..32ef171
--- /dev/null
@@ -0,0 +1,47 @@
+#include "boxblur.inc"
+#include "loadbalance.h"
+#include "vframe.h"
+
+#include <stdint.h>
+
+class BoxBlurPackage : public LoadPackage
+{
+public:
+       BoxBlurPackage();
+       int u1, u2;
+};
+
+class BoxBlurUnit : public LoadClient
+{
+public:
+       BoxBlurUnit(BoxBlur*server);
+       template<class dst_t, class src_t>
+               void blurt_package(LoadPackage *package);
+       void process_package(LoadPackage *package);
+};
+
+class BoxBlur : public LoadServer
+{
+public:
+       BoxBlur(int cpus);
+       virtual ~BoxBlur();
+       void init_packages();
+       LoadClient* new_client();
+       LoadPackage* new_package();
+       void process(VFrame *dst, VFrame *src, int uv,
+               int radius, int power, int comp);
+       void hblur(VFrame *dst, VFrame *src,
+               int radius, int power, int comp=-1);
+       void vblur(VFrame *dst, VFrame *src,
+               int radius, int power, int comp=-1);
+       void blur(VFrame *dst, VFrame *src,
+               int radius, int power, int comp=-1);
+       const uint8_t *src_data;
+       uint8_t *dst_data;
+       int src_ustep, dst_ustep;
+       int src_vstep, dst_vstep;
+       int radius, power, uv;
+       int ulen, vlen, c0, c1;
+       int src_bpp, dst_bpp;
+};
+
diff --git a/cinelerra-5.1/cinelerra/boxblur.inc b/cinelerra-5.1/cinelerra/boxblur.inc
new file mode 100644 (file)
index 0000000..8eee8b1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __BOXBLUR_INC__
+#define __BOXBLUR_INC__
+
+class BoxBlurPackage;
+class BoxBlurUnit;
+class BoxBlur;
+
+#endif
index 6488be94564e9334529dd4e365307f4977e58278..8523028966ba8ffc41319ac55ddccc24bb9d9f39 100644 (file)
@@ -171,7 +171,7 @@ void EditPanel::update()
 
 int EditPanel::calculate_w(MWindow *mwindow, int use_keyframe, int total_buttons)
 {
-       int button_w = mwindow->theme->get_image_set("meters")[0]->get_w();
+       int button_w = xS(24); // mwindow->theme->get_image_set("meters")[0]->get_w();
        int result = button_w * total_buttons;
        if( use_keyframe )
                result += 2*(button_w + mwindow->theme->toggle_margin);
index 93e0a457aba68912903ef05b7d5fe21e10700cc1..bd7f556b2cf6aba1db1f59112d390a4b99b6268f 100644 (file)
@@ -3081,7 +3081,6 @@ void MWindow::set_auto_keyframes(int value)
        gui->mbuttons->edit_panel->keyframe->update(value);
        gui->flush();
        cwindow->gui->lock_window("MWindow::set_auto_keyframes");
-       cwindow->gui->edit_panel->keyframe->update(value);
        cwindow->gui->flush();
        cwindow->gui->unlock_window();
 }
@@ -3092,7 +3091,6 @@ void MWindow::set_span_keyframes(int value)
        gui->mbuttons->edit_panel->span_keyframe->update(value);
        gui->flush();
        cwindow->gui->lock_window("MWindow::set_span_keyframes");
-       cwindow->gui->edit_panel->span_keyframe->update(value);
        cwindow->gui->flush();
        cwindow->gui->unlock_window();
 }
index 17bb811ca0eca906cd9399fb49cc382eae9e3702..b02206ab89d465467ac163e8dbe512a4b193f794 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "bcsignals.h"
 #include "bccolors.h"
+#include "boxblur.h"
 #include "clip.h"
 #include "cursors.h"
 #include "language.h"
@@ -252,7 +253,7 @@ void ScopeUnit::process_package(LoadPackage *package)
                break;
        case BC_RGB_FLOAT:
                for( int y=pkg->row1; y<pkg->row2; ++y ) {
-                       float *row = (float*)rows[y];
+                       uint8_t *row = rows[y];
                        for( int x=0; x<dat_w; ++x ) {
                                PROCESS_RGB_PIXEL(float,1.f, x)
                                row += 3*sizeof(float);
@@ -261,7 +262,7 @@ void ScopeUnit::process_package(LoadPackage *package)
                break;
        case BC_RGBA_FLOAT:
                for( int y=pkg->row1; y<pkg->row2; ++y ) {
-                       float *row = (float*)rows[y];
+                       uint8_t *row = rows[y];
                        for( int x=0; x<dat_w; ++x ) {
                                PROCESS_RGB_PIXEL(float,1.f, x)
                                row += 4*sizeof(float);
@@ -402,6 +403,8 @@ ScopeGUI::ScopeGUI(PluginClient *plugin, int w, int h)
        this->temp_frame = 0;
        this->theme = plugin->get_theme();
        this->cpus = plugin->PluginClient::smp + 1;
+       wave_slider = 0;
+       vect_slider = 0;
        reset();
 }
 
@@ -412,6 +415,8 @@ ScopeGUI::~ScopeGUI()
        delete engine;
        delete box_blur;
        delete temp_frame;
+       delete wave_slider;
+       delete vect_slider;
 }
 
 void ScopeGUI::reset()
@@ -471,12 +476,13 @@ void ScopeGUI::create_panels()
        int slider_w = xS(100);
        if( (use_wave || use_wave_parade) ) {
                int px = wave_x + wave_w - slider_w - xS(5);
-               int py = wave_y - ScopeWaveSlider::get_span(0) - yS(5);
+               int py = wave_y - ScopeGain::calculate_h() - yS(5);
                if( !waveform ) {
                        add_subwindow(waveform = new ScopeWaveform(this,
                                wave_x, wave_y, wave_w, wave_h));
                        waveform->create_objects();
-                       add_subwindow(wave_slider = new ScopeWaveSlider(this, px, py, slider_w));
+                       wave_slider = new ScopeWaveSlider(this, px, py, slider_w);
+                       wave_slider->create_objects();
                }
                else {
                        waveform->reposition_window(
@@ -492,12 +498,13 @@ void ScopeGUI::create_panels()
 
        if( use_vector ) {
                int vx = vector_x + vector_w - slider_w - xS(5);
-               int vy = vector_y - ScopeVectSlider::get_span(0) - yS(5);
+               int vy = vector_y - ScopeGain::calculate_h() - yS(5);
                if( !vectorscope ) {
                        add_subwindow(vectorscope = new ScopeVectorscope(this,
                                vector_x, vector_y, vector_w, vector_h));
                        vectorscope->create_objects();
-                       add_subwindow(vect_slider = new ScopeVectSlider(this, vx, vy, slider_w));
+                       vect_slider = new ScopeVectSlider(this, vx, vy, slider_w);
+                       vect_slider->create_objects();
                }
                else {
                        vectorscope->reposition_window(
@@ -1144,194 +1151,101 @@ void ScopeMenu::update_toggles()
        vect_on->set_checked(gui->use_vector);
 }
 
-ScopeWaveSlider::ScopeWaveSlider(ScopeGUI *gui, int x, int y, int w)
- : BC_ISlider(x, y, 0, w, w, 1, 9, gui->use_wave_gain)
+
+ScopeGainReset::ScopeGainReset(ScopeGain *gain, int x, int y)
+ : BC_Button(x, y, gain->gui->theme->get_image_set("reset_button"))
 {
-       this->gui = gui;
-}
-int ScopeWaveSlider::handle_event()
-{
-       gui->use_wave_gain = get_value();
-       gui->update_scope();
-       gui->toggle_event();
-       return 1;
+       this->gain = gain;
 }
 
-ScopeVectSlider::ScopeVectSlider(ScopeGUI *gui, int x, int y, int w)
- : BC_ISlider(x, y, 0, w, w, 1, 9, gui->use_vect_gain)
+int ScopeGainReset::calculate_w(BC_Theme *theme)
 {
-       this->gui = gui;
+       VFrame *vfrm = *theme->get_image_set("reset_button");
+       return vfrm->get_w();
 }
-int ScopeVectSlider::handle_event()
+
+int ScopeGainReset::handle_event()
 {
-       gui->use_vect_gain = get_value();
-       gui->update_scope();
-       gui->toggle_event();
-       return 1;
+       gain->slider->update(5);
+       return gain->handle_event();
 }
 
-ScopeSmooth::ScopeSmooth(ScopeGUI *gui, int x, int y)
- : BC_CheckBox(x, y, gui->use_smooth, _("Smooth"))
+ScopeGainSlider::ScopeGainSlider(ScopeGain *gain, int x, int y, int w)
+ : BC_ISlider(x, y, 0, w, w, 1, 9, *gain->value)
 {
-       this->gui = gui;
+       this->gain = gain;
 }
 
-int ScopeSmooth::handle_event()
+int ScopeGainSlider::handle_event()
 {
-       gui->use_smooth = get_value();
-       gui->update_scope();
-       gui->toggle_event();
-       return 1;
+       return gain->handle_event();
 }
 
-// from ffmpeg vf_boxblur
-template<class dst_t, class src_t> static inline
-void blurt(dst_t *dst, int dst_step, src_t *src, int src_step, int len, int radius)
+ScopeGain::ScopeGain(ScopeGUI *gui, int x, int y, int w, int *value)
 {
-       const int length = radius*2 + 1;
-       const int inv = ((1<<16) + length/2)/length;
-       int x, n, sum = src[radius*src_step];
-
-       for( x=0; x<radius; ++x )
-               sum += src[x*src_step]<<1;
-       sum = sum*inv + (1<<15);
-
-       for( x=0; x<=radius; ++x ) {
-               sum += (src[(radius+x)*src_step] - src[(radius-x)*src_step])*inv;
-               dst[x*dst_step] = sum>>16;
-       }
-       n = len - radius;
-       for( ; x<n; ++x ) {
-               sum += (src[(radius+x)*src_step] - src[(x-radius-1)*src_step])*inv;
-               dst[x*dst_step] = sum >>16;
-       }
+       this->gui = gui;
+       this->x = x;
+       this->y = y;
+       this->w = w;
+       this->value = value;
 
-       for ( ; x<len; ++x ) {
-               sum += (src[(2*len-radius-x-1)*src_step] - src[(x-radius-1)*src_step])*inv;
-               dst[x*dst_step] = sum>>16;
-       }
+       slider = 0;
+       reset = 0;
 }
-template<class dst_t, class src_t> static inline
-void blur_power(dst_t *dst, int dst_step, src_t *src, int src_step,
-               int len, int radius, int power)
-{
-       dst_t atemp[len], btemp[len];
-       dst_t *a = atemp, *b = btemp;
-       blurt(a, 1, src, src_step, len, radius);
-       while( power-- > 2 ) {
-               blurt(b, 1, a, 1, len, radius);
-               dst_t *t = a; a = b; b = t;
-        }
-       if( power > 1 )
-               blurt(dst, dst_step, a, 1, len, radius);
-       else
-                for( int i = 0; i<len; ++i ) dst[i*dst_step] = a[i];
-}
-
-
-BoxBlurPackage::BoxBlurPackage()
- : LoadPackage()
+ScopeGain::~ScopeGain()
 {
+       delete reset;
+       delete slider;
 }
 
-BoxBlurUnit::BoxBlurUnit(BoxBlur *box_blur)
- : LoadClient(box_blur)
+int ScopeGain::calculate_h()
 {
+       return BC_ISlider::get_span(0);
 }
 
-template<class dst_t, class src_t>
-void BoxBlurUnit::blurt_package(LoadPackage *package)
+void ScopeGain::create_objects()
 {
-       BoxBlur *box_blur = (BoxBlur *)server;
-       src_t *src_data = (src_t *)box_blur->src_data;
-       dst_t *dst_data = (dst_t *)box_blur->dst_data;
-       int radius = box_blur->radius;
-       int power = box_blur->power;
-       int vlen = box_blur->vlen;
-       int c0 = box_blur->c0, c1 = box_blur->c1;
-       int src_ustep = box_blur->src_ustep;
-       int dst_ustep = box_blur->dst_ustep;
-       int src_vstep = box_blur->src_vstep;
-       int dst_vstep = box_blur->dst_vstep;
-       BoxBlurPackage *pkg = (BoxBlurPackage*)package;
-       int u1 = pkg->u1, u2 = pkg->u2;
-       for( int u=u1; u<u2; ++u ) {
-               src_t *sp = src_data + u*src_ustep;
-               dst_t *dp = dst_data + u*dst_ustep;
-               for( int c=c0; c<=c1; ++c ) {
-                       blur_power(dp+c, dst_vstep, sp+c, src_vstep,
-                               vlen, radius, power);
-               }
-       }
+       reset_w = ScopeGainReset::calculate_w(gui->theme);
+       gui->add_subwindow(slider = new ScopeGainSlider(this, x, y, w-reset_w-xS(5)));
+       gui->add_subwindow(reset = new ScopeGainReset(this, x+w-reset_w, y));
 }
 
-void BoxBlurUnit::process_package(LoadPackage *package)
+int ScopeGain::handle_event()
 {
-       blurt_package<uint16_t, const uint16_t>(package);
+       *value = slider->get_value();
+       gui->update_scope();
+       gui->toggle_event();
+       return 1;
 }
 
-BoxBlur::BoxBlur(int cpus)
- : LoadServer(cpus, cpus)
-{
-}
-BoxBlur::~BoxBlur()
+void ScopeGain::reposition_window(int x, int y)
 {
+       this->x = x;  this->y = y;
+       slider->reposition_window(x, y);
+       reset->reposition_window(x+w-reset_w, y);
 }
 
-LoadClient* BoxBlur::new_client() { return new BoxBlurUnit(this); }
-LoadPackage* BoxBlur::new_package() { return new BoxBlurPackage(); }
-
-void BoxBlur::init_packages()
+ScopeWaveSlider::ScopeWaveSlider(ScopeGUI *gui, int x, int y, int w)
+ : ScopeGain(gui, x, y, w, &gui->use_wave_gain)
 {
-       int u = 0;
-       for( int i=0,n=LoadServer::get_total_packages(); i<n; ) {
-               BoxBlurPackage *pkg = (BoxBlurPackage*)get_package(i);
-               pkg->u1 = u;
-               pkg->u2 = u = (++i * ulen) / n;
-       }
-}
-
-//dst can equal src, requires geom(dst)==geom(src)
-//uv: 0=hblur, 1=vblur;  comp: -1=rgb,0=r,1=g,2=b
-void BoxBlur::process(VFrame *dst, VFrame *src, int uv,
-               int radius, int power, int comp)
-{
-       this->radius = radius;
-       this->power = power;
-       int src_w = src->get_w(), src_h = src->get_h();
-       ulen = !uv ? src_h : src_w;
-       vlen = !uv ? src_w : src_h;
-       c0 = comp<0 ? 0 : comp;
-       c1 = comp<0 ? 2 : comp;
-       src_data = src->get_data();
-       dst_data = dst->get_data();
-       int src_pixsz = BC_CModels::calculate_pixelsize(src->get_color_model());
-       int src_comps = BC_CModels::components(src->get_color_model());
-       int src_bpp = src_pixsz / src_comps;
-       int dst_pixsz = BC_CModels::calculate_pixelsize(dst->get_color_model());
-       int dst_comps = BC_CModels::components(dst->get_color_model());
-       int dst_bpp = dst_pixsz / dst_comps;
-       int dst_linsz = dst->get_bytes_per_line() / dst_bpp;
-       int src_linsz = src->get_bytes_per_line() / src_bpp;
-       src_ustep = !uv ? src_linsz : src_comps;
-       dst_ustep = !uv ? dst_linsz: dst_comps;
-       src_vstep = !uv ? src_comps : src_linsz;
-       dst_vstep = !uv ? dst_comps : dst_linsz;
-
-       process_packages();
 }
 
-void BoxBlur::hblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+ScopeVectSlider::ScopeVectSlider(ScopeGUI *gui, int x, int y, int w)
+ : ScopeGain(gui, x, y, w, &gui->use_vect_gain)
 {
-       process(dst, src, 0, radius, power, comp);
 }
-void BoxBlur::vblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+
+ScopeSmooth::ScopeSmooth(ScopeGUI *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->use_smooth, _("Smooth"))
 {
-       process(dst, src, 1, radius, power, comp);
+       this->gui = gui;
 }
-void BoxBlur::blur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+
+int ScopeSmooth::handle_event()
 {
-       process(dst, src, 0, radius, power, comp);
-       process(dst, dst, 1, radius, power, comp);
+       gui->use_smooth = get_value();
+       gui->update_scope();
+       gui->toggle_event();
+       return 1;
 }
 
index 74201e460f4520a88ee50be2c531c6c3550fe304..86f9efa91155147d2c94fc6988057ace0dd9d21a 100644 (file)
@@ -22,6 +22,7 @@
 #define SCOPEWINDOW_H
 
 
+#include "boxblur.inc"
 #include "guicast.h"
 #include "loadbalance.h"
 #include "mwindow.h"
@@ -161,22 +162,61 @@ public:
        ScopeScopesOn *vect_on;
 };
 
-class ScopeWaveSlider : public BC_ISlider
+
+class ScopeGainReset : public BC_Button
 {
 public:
-       ScopeWaveSlider(ScopeGUI *gui, int x, int y, int w);
+       ScopeGainReset(ScopeGain *gain, int x, int y);
+       static int calculate_w(BC_Theme *theme);
        int handle_event();
-       ScopeGUI *gui;
+
+       ScopeGain *gain;
 };
 
-class ScopeVectSlider : public BC_ISlider
+class ScopeGainSlider : public BC_ISlider
 {
 public:
-       ScopeVectSlider(ScopeGUI *gui, int x, int y, int w);
+       ScopeGainSlider(ScopeGain *gain, int x, int y, int w);
+
        int handle_event();
+       ScopeGain *gain;
+};
+
+class ScopeGain
+{
+public:
+       ScopeGain(ScopeGUI *gui, int x, int y, int w, int *value);
+       ~ScopeGain();
+       static int calculate_h();
+       void create_objects();
+       void reposition_window(int x, int y);
+       int handle_event();
+
        ScopeGUI *gui;
+       int x, y, w, *value;
+       int reset_w;
+       ScopeGainReset *reset;
+       ScopeGainSlider *slider;
+
+       int get_x() { return x; }
+       int get_y() { return y; }
+       int get_w() { return w; }
+       int get_h() { return calculate_h(); }
+};
+
+class ScopeWaveSlider : public ScopeGain
+{
+public:
+       ScopeWaveSlider(ScopeGUI *gui, int x, int y, int w);
 };
 
+class ScopeVectSlider : public ScopeGain
+{
+public:
+       ScopeVectSlider(ScopeGUI *gui, int x, int y, int w);
+};
+
+
 class ScopeSmooth : public BC_CheckBox
 {
 public:
@@ -242,45 +282,4 @@ public:
        int use_wave_gain, use_vect_gain;
 };
 
-
-class BoxBlurPackage : public LoadPackage
-{
-public:
-       BoxBlurPackage();
-       int u1, u2;
-};
-
-class BoxBlurUnit : public LoadClient
-{
-public:
-       BoxBlurUnit(BoxBlur*server);
-       template<class dst_t, class src_t>
-               void blurt_package(LoadPackage *package);
-       void process_package(LoadPackage *package);
-};
-
-class BoxBlur : public LoadServer
-{
-public:
-       BoxBlur(int cpus);
-       virtual ~BoxBlur();
-       void init_packages();
-       LoadClient* new_client();
-       LoadPackage* new_package();
-       void process(VFrame *dst, VFrame *src, int uv,
-               int radius, int power, int comp);
-       void hblur(VFrame *dst, VFrame *src,
-               int radius, int power, int comp=-1);
-       void vblur(VFrame *dst, VFrame *src,
-               int radius, int power, int comp=-1);
-       void blur(VFrame *dst, VFrame *src,
-               int radius, int power, int comp=-1);
-       const uint8_t *src_data;
-       uint8_t *dst_data;
-       int src_ustep, dst_ustep;
-       int src_vstep, dst_vstep;
-       int radius, power;
-       int ulen, vlen, c0, c1;
-};
-
 #endif
index 3da8bd28ebe4f98451749524bcb90f1014693eb0..a59475a12357a1bcfa893abc4fa847b888ff07bf 100644 (file)
@@ -1,23 +1,3 @@
-/*
- * CINELERRA
- * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
 #ifndef SCOPEWINDOW_INC
 #define SCOPEWINDOW_INC
 
@@ -30,16 +10,12 @@ class ScopeVectorscope;
 class ScopeHistogram;
 class ScopeScopesOn;
 class ScopeMenu;
-class ScopeWaveDial;
-class ScopeVectDial;
+class ScopeGainReset;
+class ScopeGainSlider;
+class ScopeGain;
+class ScopeWaveSlider;
+class ScopeVectSlider;
 class ScopeSmooth;
 class ScopeGUI;
 
-class BoxBlurPackage;
-class BoxBlurUnit;
-class BoxBlur;
-
 #endif
-
-
-
index 80ca335c5d78a7dde1fe95ddddeda873e27a3c04..71bb2399ae82e4d8672238f0f0cb1fdf4fb4411d 100644 (file)
@@ -730,35 +730,35 @@ SET_TRACE
                }
                else
                {
-                       cmeter_x = mwindow->session->cwindow_w + widget_border;
+                       cmeter_x = mwindow->session->cwindow_w;
                }
 
-               int edit_panel_h = EditPanel::calculate_h(mwindow);
-               int buttons_h = 0;
-               if( edit_w + widget_border * 2 + transport_w + widget_border +
-                   zoom_w + widget_border + division_w + status_w > cmeter_x ) {
-                       buttons_h = (widget_border + edit_panel_h) * 2;
-                       ctransport_x = widget_border;
-                       ctransport_y = mwindow->session->cwindow_h - buttons_h;
-                       czoom_x = ctransport_x + transport_w + widget_border;
-                       czoom_y = ctransport_y;
+
+               int buttons_h = get_image("rewind")->get_h() + widget_border;
+               ctransport_x = widget_border;
+               ctransport_y = mwindow->session->cwindow_h - buttons_h - widget_border;
+               if( ctransport_x + transport_w + widget_border +
+                   edit_w + widget_border + zoom_w + widget_border +
+                   division_w + status_w > cmeter_x ) {
+                       buttons_h += EditPanel::calculate_h(mwindow) + widget_border;
                        cedit_x = widget_border;
-                       cedit_y = ctransport_y + edit_panel_h + widget_border;
+                       cedit_y = mwindow->session->cwindow_h - buttons_h;
+                       czoom_x = ctransport_x + transport_w + widget_border;
+                       czoom_y = ctransport_y + widget_border;
+                       cstatus_x = xS(440);
+                       cstatus_y = cedit_y + yS(20);
                }
                else {
-                       buttons_h = widget_border + edit_panel_h;
                        ctransport_x = widget_border;
                        ctransport_y = mwindow->session->cwindow_h - buttons_h;
                        cedit_x = ctransport_x + transport_w + widget_border;
                        cedit_y = ctransport_y;
                        czoom_x = cedit_x + edit_w + widget_border;
-                       czoom_y = ctransport_y;
+                       czoom_y = cedit_y + widget_border;
+                       cstatus_x = czoom_x + zoom_w + division_w;
+                       cstatus_y = ctransport_y;
                }
-               buttons_h += ctimebar_h + widget_border;
-
-               cstatus_x = mwindow->session->cwindow_w - xS(50);
-               cstatus_y = mwindow->session->cwindow_h -
-                       get_image("cwindow_active")->get_h() - yS(5);
+               buttons_h += ctimebar_h;
 
                ccomposite_x = xS(0);
                ccomposite_y = yS(5);
@@ -906,14 +906,13 @@ void Theme::get_vwindow_sizes(VWindowGUI *gui)
        int transport_w = PlayTransport::get_transport_width(mwindow) + toggle_margin;
 // Space between buttons & time
        int division_w = xS(30);
-       vtime_w = xS(150);
+       vtime_w = xS(120);
        vtimebar_h = yS(16);
        int vtime_border = xS(15);
 
        vmeter_y = widget_border;
        vmeter_h = mwindow->session->vwindow_h - cmeter_y - widget_border;
 
-       int buttons_h;
        if(mwindow->edl->session->vwindow_meter)
        {
                vmeter_x = mwindow->session->vwindow_w -
@@ -923,55 +922,37 @@ void Theme::get_vwindow_sizes(VWindowGUI *gui)
        }
        else
        {
-               vmeter_x = mwindow->session->vwindow_w + widget_border;
+               vmeter_x = mwindow->session->vwindow_w;
        }
 
        vcanvas_x = 0;
        vcanvas_y = 0;
        vcanvas_w = vmeter_x - vcanvas_x - widget_border;
 
-       if(edit_w +
-               widget_border * 2 +
-               transport_w + widget_border +
-               vtime_w + division_w +
-               vtime_border > vmeter_x)
-       {
-               buttons_h = get_image("vbuttons_left")->get_h();
+       int buttons_h = get_image("rewind")->get_h() + widget_border;
+       vtransport_x = widget_border;
+       vtransport_y = mwindow->session->vwindow_h - buttons_h - widget_border;
+       if( vtransport_x + transport_w + widget_border +
+           edit_w + widget_border + vtime_w + xS(40) + widget_border > vmeter_x ) {
+               buttons_h += EditPanel::calculate_h(mwindow) + widget_border;
                vedit_x = widget_border;
-               vedit_y = mwindow->session->vwindow_h -
-                       buttons_h +
-                       vtimebar_h +
-                       widget_border;
-
-               vtransport_x = widget_border;
-               vtransport_y = mwindow->session->vwindow_h -
-                       get_image_set("autokeyframe")[0]->get_h() -
-                       widget_border;
-
+               vedit_y = mwindow->session->vwindow_h - buttons_h;
+               vzoom_x = vtransport_x + transport_w + widget_border;
+               vzoom_y = vtransport_y + widget_border;
                vdivision_x = xS(280);
-               vtime_x = vedit_x + xS(20); //vdivision_x;
-               vtime_y = vedit_y + yS(30); //+ yS(20);
+               vtime_x = vdivision_x;
+               vtime_y = vtransport_y + widget_border;;
        }
-       else
-       {
-               buttons_h = vtimebar_h +
-                       widget_border +
-                       EditPanel::calculate_h(mwindow) +
-                       widget_border;
+       else {
                vtransport_x = widget_border;
-               vtransport_y = mwindow->session->vwindow_h -
-                       buttons_h +
-                       vtimebar_h +
-                       widget_border;
-
+               vtransport_y = mwindow->session->vwindow_h - buttons_h;
                vedit_x = vtransport_x + transport_w + widget_border;
                vedit_y = vtransport_y;
-
                vdivision_x = vedit_x + edit_w + division_w;
                vtime_x = vdivision_x + vtime_border;
-               vtime_y = vedit_y + widget_border;
+               vtime_y = vtransport_y + widget_border;;
        }
-
+       buttons_h += vtimebar_h;
 
 //     vtimebar_x = vcanvas_x;
 //     vtimebar_y = vcanvas_y + vcanvas_h;
@@ -981,7 +962,6 @@ void Theme::get_vwindow_sizes(VWindowGUI *gui)
        vtimebar_x = 0;
        vtimebar_y = vcanvas_y + vcanvas_h;
        vtimebar_w = vmeter_x - widget_border;
-
 }
 
 
index 2c7c62a89dd324afc2c355515287d666e2956f2a..c8cabb8b677983ce774497a7a024724fe98c77ea 100644 (file)
@@ -29,6 +29,9 @@ Blue Banana:  Used for color transformation or remapping as
                4) adjust your color choice as desired
 Blur:          Blurs a video track in horizontal and/or
                vertical in chosen color channels.
+BoxBlur:       Blurs the input video.  This fairly fast blur is
+               based on ffmpeg's, and blurs in horizontal and/or
+               vertical with power.
 Brightness/Contrast: Use to change the brightness or
                contrast, but could reduce quality.
 BurningTV:     Makes your video "burn" where there are
index fcac5dd5cfd74b1cea74601f68b7c2f516e13dcf..acce1afd6e7e7a508a850f423a3343c48631f3a1 100644 (file)
@@ -7,6 +7,12 @@ Cinfinity icons selected in Preferences Sam (CC BY 3.0,
 Cakewalk and Neophyte themes by Olaf Wolff (CC BY 4.0,
   https://creativecommons.org/licenses/by/4.0/)
 .
+March 2020 New Feature of note:
+  Videoscope is now on the Compositor and Viewer.
+  Additional enhancements made for the Videoscope.
+  Several new Shape Wipe transitions are included.
+  Slider bars added to Projector and Camera menus.
+  OpenCV and OpenExr have been upgraded on some O/S.
 February 2020 New Features of note:
   New ColorSpace plugin to convert color space/range.
   Updated 17 thirdparty libraries to keep up to date.
index e63682dca787dfb7aed490c7778f95e7123b745a..0777e924bda5fec9df036e9c360119064c846698 100644 (file)
@@ -33,6 +33,7 @@ DIRS = $(OPENCV_OBJS) \
        bandwipe \
        bluebanana \
        blur \
+       boxblur \
        brightness \
        burn \
        C41 \
diff --git a/cinelerra-5.1/plugins/boxblur/Makefile b/cinelerra-5.1/plugins/boxblur/Makefile
new file mode 100644 (file)
index 0000000..24f4d02
--- /dev/null
@@ -0,0 +1,9 @@
+include ../../plugin_defs
+
+OBJS = $(OBJDIR)/boxblur.o
+
+PLUGIN = boxblur
+
+include ../../plugin_config
+
+$(OBJDIR)/boxblur.o: boxblur.C
diff --git a/cinelerra-5.1/plugins/boxblur/boxblur.C b/cinelerra-5.1/plugins/boxblur/boxblur.C
new file mode 100644 (file)
index 0000000..b141fe6
--- /dev/null
@@ -0,0 +1,271 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2020 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "guicast.h"
+#include "boxblur.h"
+#include "filexml.h"
+#include "language.h"
+#include "pluginvclient.h"
+#include "theme.h"
+
+#include <stdint.h>
+#include <string.h>
+
+class BoxBlurConfig;
+class BoxBlurRadius;
+class BoxBlurPower;
+class BoxBlurWindow;
+class BoxBlurEffect;
+
+
+class BoxBlurConfig
+{
+public:
+       BoxBlurConfig();
+       void copy_from(BoxBlurConfig &that);
+       int equivalent(BoxBlurConfig &that);
+       void interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
+               long prev_frame, long next_frame, long current_frame);
+
+       int horz_radius, vert_radius, power;
+};
+
+
+class BoxBlurRadius : public BC_ISlider
+{
+public:
+       BoxBlurRadius(BoxBlurWindow *gui, int x, int y, int w, int *radius);
+       int handle_event();
+
+       BoxBlurWindow *gui;
+       int *radius;
+};
+
+class BoxBlurPower : public BC_ISlider
+{
+public:
+       BoxBlurPower(BoxBlurWindow *gui, int x, int y, int w, int *power);
+       int handle_event();
+
+       BoxBlurWindow *gui;
+       int *power;
+};
+
+class BoxBlurWindow : public PluginClientWindow
+{
+public:
+       BoxBlurWindow(BoxBlurEffect *plugin);
+       ~BoxBlurWindow();
+       void create_objects();
+
+       BoxBlurEffect *plugin;
+       BoxBlurRadius *blur_horz;
+       BoxBlurRadius *blur_vert;
+       BoxBlurPower *blur_power;
+};
+
+
+
+class BoxBlurEffect : public PluginVClient
+{
+public:
+       BoxBlurEffect(PluginServer *server);
+       ~BoxBlurEffect();
+
+       PLUGIN_CLASS_MEMBERS(BoxBlurConfig)
+       int process_realtime(VFrame *input, VFrame *output);
+       void update_gui();
+       int is_realtime();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+
+       BoxBlur *box_blur;
+};
+
+
+BoxBlurConfig::BoxBlurConfig()
+{
+       horz_radius = 2;
+       vert_radius = 2;
+       power = 2;
+}
+
+void BoxBlurConfig::copy_from(BoxBlurConfig &that)
+{
+       horz_radius = that.horz_radius;
+       vert_radius = that.vert_radius;
+       power = that.power;
+}
+
+int BoxBlurConfig::equivalent(BoxBlurConfig &that)
+{
+       return horz_radius == that.horz_radius &&
+               vert_radius == that.vert_radius &&
+               power == that.power;
+}
+
+void BoxBlurConfig::interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
+       int64_t prev_frame, int64_t next_frame, int64_t current_frame)
+{
+       double u = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+       double v = 1. - u;
+       this->horz_radius = u*prev.horz_radius + v*next.horz_radius;
+       this->vert_radius = u*prev.vert_radius + v*next.vert_radius;
+       this->power = u*prev.power + v*next.power;
+}
+
+
+BoxBlurRadius::BoxBlurRadius(BoxBlurWindow *gui, int x, int y, int w, int *radius)
+ : BC_ISlider(x, y, 0, w, w, 0, 100, *radius)
+{
+       this->gui = gui;
+       this->radius = radius;
+}
+int BoxBlurRadius::handle_event()
+{
+       *radius = get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+BoxBlurPower::BoxBlurPower(BoxBlurWindow *gui, int x, int y, int w, int *power)
+ : BC_ISlider(x, y, 0, w, w, 1, 10, *power)
+{
+       this->gui = gui;
+       this->power = power;
+}
+int BoxBlurPower::handle_event()
+{
+       *power = get_value();
+       gui->plugin->send_configure_change();
+       return 1;
+}
+
+BoxBlurWindow::BoxBlurWindow(BoxBlurEffect *plugin)
+ : PluginClientWindow(plugin, xS(200), yS(120), xS(200), yS(120), 0)
+{
+       this->plugin = plugin;
+}
+
+BoxBlurWindow::~BoxBlurWindow()
+{
+}
+
+void BoxBlurWindow::create_objects()
+{
+       int x = xS(10), y = yS(10);
+       int x1 = xS(70), margin = plugin->get_theme()->widget_border;
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x, y, _("Box Blur"), MEDIUMFONT, YELLOW));
+       y += title->get_h() + 2*margin;
+       add_subwindow(title = new BC_Title(x, y, _("Horz:")));
+       add_subwindow(blur_horz = new BoxBlurRadius(this, x1, y, xS(120),
+               &plugin->config.horz_radius));
+       y += blur_horz->get_h() + margin;
+       add_subwindow(title = new BC_Title(x, y, _("Vert:")));
+       add_subwindow(blur_vert = new BoxBlurRadius(this, x1, y, xS(120),
+               &plugin->config.vert_radius));
+       y += blur_vert->get_h() + margin;
+       add_subwindow(title = new BC_Title(x, y, _("Power:")));
+       add_subwindow(blur_power = new BoxBlurPower(this, x1, y, xS(120),
+               &plugin->config.power));
+       show_window(1);
+}
+
+
+REGISTER_PLUGIN(BoxBlurEffect)
+NEW_WINDOW_MACRO(BoxBlurEffect, BoxBlurWindow)
+LOAD_CONFIGURATION_MACRO(BoxBlurEffect, BoxBlurConfig)
+
+
+BoxBlurEffect::BoxBlurEffect(PluginServer *server)
+ : PluginVClient(server)
+{
+       box_blur = 0;
+}
+
+BoxBlurEffect::~BoxBlurEffect()
+{
+       delete box_blur;
+}
+
+const char* BoxBlurEffect::plugin_title() { return N_("BoxBlur"); }
+int BoxBlurEffect::is_realtime() { return 1; }
+
+
+void BoxBlurEffect::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+       output.set_shared_output(keyframe->xbuf);
+       output.tag.set_title("BOXBLUR");
+       output.tag.set_property("HORZ_RADIUS", config.horz_radius);
+       output.tag.set_property("VERT_RADIUS", config.vert_radius);
+       output.tag.set_property("POWER", config.power);
+       output.append_tag();
+       output.tag.set_title("/BOXBLUR");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+}
+
+void BoxBlurEffect::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       input.set_shared_input(keyframe->xbuf);
+       int result = 0;
+
+       while( !(result = input.read_tag()) ) {
+               if( input.tag.title_is("BOXBLUR") ) {
+                       config.horz_radius = input.tag.get_property("HORZ_RADIUS", config.horz_radius);
+                       config.vert_radius = input.tag.get_property("VERT_RADIUS", config.vert_radius);
+                       config.power = input.tag.get_property("POWER", config.power);
+               }
+       }
+}
+
+int BoxBlurEffect::process_realtime(VFrame *input, VFrame *output)
+{
+       load_configuration();
+       if( !box_blur ) {
+               int cpus = input->get_w()*input->get_h()/0x80000 + 1;
+               box_blur = new BoxBlur(cpus);
+       }
+       if( config.horz_radius ) {
+               box_blur->hblur(output, input, config.horz_radius, config.power);
+               input = output;
+       }
+       if( config.vert_radius )
+               box_blur->vblur(output, input, config.vert_radius, config.power);
+       return 1;
+}
+
+void BoxBlurEffect::update_gui()
+{
+       if( !thread ) return;
+       load_configuration();
+       thread->window->lock_window("BoxBlurEffect::update_gui");
+       BoxBlurWindow *gui = (BoxBlurWindow *)thread->window;
+       gui->blur_horz->update(config.horz_radius);
+       gui->blur_vert->update(config.vert_radius);
+       gui->blur_power->update(config.power);
+       thread->window->unlock_window();
+}
+