add yuv411 plugin
authorGood Guy <good1.2guy@gmail.com>
Sun, 28 Aug 2016 18:28:15 +0000 (12:28 -0600)
committerGood Guy <good1.2guy@gmail.com>
Sun, 28 Aug 2016 18:28:15 +0000 (12:28 -0600)
cinelerra-5.1/plugin_defs
cinelerra-5.1/plugins/Makefile
cinelerra-5.1/plugins/yuv411/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/yuv411/picon.png [new file with mode: 0644]
cinelerra-5.1/plugins/yuv411/yuv411.C [new file with mode: 0644]
cinelerra-5.1/plugins/yuv411/yuv411.h [new file with mode: 0644]
cinelerra-5.1/plugins/yuv411/yuv411win.C [new file with mode: 0644]
cinelerra-5.1/plugins/yuv411/yuv411win.h [new file with mode: 0644]

index bf9e8c379ab32caebc428a272ee45a4aa69407d3..848f58163016d68598bf36996b3cce69a8c97988 100644 (file)
@@ -44,7 +44,7 @@ blending := chromakeyhsv chromakey diffkey
 
 plugin_dirs += tv_effects
 tv_effects := deinterlace-cv deinterlace ivtc liveaudio livevideo rgb601 \
-       rgbshift shiftinterlace swapchannels swapframes yuv yuvshift
+       rgbshift shiftinterlace swapchannels swapframes yuv yuv411 yuvshift
 
 $(foreach dir,$(plugin_dirs),$(foreach plugin,$($(dir)), $(eval $(plugin):=$(dir))))
 
index 09ae02694652d75b773186c52da641251b686f7e..c233f06c66693e0ba10146644db5f8cd8b001732 100644 (file)
@@ -126,6 +126,7 @@ DIRS = \
        whirl \
        wipe \
        yuv \
+       yuv411 \
        yuvshift \
        zoom \
        zoomblur \
diff --git a/cinelerra-5.1/plugins/yuv411/Makefile b/cinelerra-5.1/plugins/yuv411/Makefile
new file mode 100644 (file)
index 0000000..97e2d2d
--- /dev/null
@@ -0,0 +1,12 @@
+include ../../plugin_defs
+
+OBJS =  $(OBJDIR)/yuv411.o  \
+        $(OBJDIR)/yuv411win.o
+
+PLUGIN = yuv411
+
+include ../../plugin_config
+
+$(OBJDIR)/yuv411.o: yuv411.C
+$(OBJDIR)/yuv411win.o: yuv411win.C
+
diff --git a/cinelerra-5.1/plugins/yuv411/picon.png b/cinelerra-5.1/plugins/yuv411/picon.png
new file mode 100644 (file)
index 0000000..e389da3
Binary files /dev/null and b/cinelerra-5.1/plugins/yuv411/picon.png differ
diff --git a/cinelerra-5.1/plugins/yuv411/yuv411.C b/cinelerra-5.1/plugins/yuv411/yuv411.C
new file mode 100644 (file)
index 0000000..161ae33
--- /dev/null
@@ -0,0 +1,292 @@
+#include "clip.h"
+#include "bccmodels.h"
+#include "bchash.h"
+#include "filexml.h"
+#include "yuv411.h"
+#include "yuv411win.h"
+#include "language.h"
+
+#include <stdint.h>
+#include <string.h>
+
+REGISTER_PLUGIN(yuv411Main)
+
+
+yuv411Config::yuv411Config()
+{
+       int_horizontal = 0;
+       avg_vertical = 0;
+       inpainting = 0;
+       offset = 1;
+       thresh = 4;
+       bias = 1;
+}
+
+void yuv411Config::copy_from(yuv411Config &that)
+{
+       int_horizontal = that.int_horizontal;
+       avg_vertical = that.avg_vertical;
+       inpainting = that.inpainting;
+       offset = that.offset;
+       thresh = that.thresh;
+       bias = that.bias;
+}
+
+int yuv411Config::equivalent(yuv411Config &that)
+{
+       return int_horizontal == that.int_horizontal &&
+               avg_vertical == that.avg_vertical &&
+               inpainting == that.inpainting &&
+               offset == that.offset &&
+               thresh == that.thresh &&
+               bias == that.bias;
+}
+
+void yuv411Config::interpolate(yuv411Config &prev, 
+       yuv411Config &next, 
+       long prev_frame, 
+       long next_frame, 
+       long current_frame)
+{
+       this->int_horizontal = prev.int_horizontal;
+       this->avg_vertical = prev.avg_vertical;
+       this->inpainting = prev.inpainting;
+       this->offset = prev.offset;
+       this->thresh = prev.thresh;
+       this->bias = prev.bias;
+}
+
+
+yuv411Main::yuv411Main(PluginServer *server)
+ : PluginVClient(server)
+{
+       this->server = server;
+       this->temp_frame = 0;
+       colormodel = -1;
+}
+
+yuv411Main::~yuv411Main()
+{
+       delete temp_frame;
+}
+
+const char *yuv411Main::plugin_title() { return _("YUV411"); }
+int yuv411Main::is_realtime() { return 1; }
+       
+#define YUV411_MACRO(type, components) \
+{ \
+    type **input_rows = ((type**)input_ptr->get_rows()), **in_rows = input_rows; \
+    type **output_rows = ((type**)output_ptr->get_rows()), **out_rows = output_rows; \
+    if( config.avg_vertical ) { \
+        if( config.int_horizontal ) \
+            in_rows = out_rows = ((type**)temp_frame->get_rows()); \
+        for( int i=0,h3=h-3; i<h3; i+=4 ) { \
+            type *in_row0 = input_rows[i+0], *in_row1 = input_rows[i+1]; \
+            type *in_row2 = input_rows[i+2], *in_row3 = input_rows[i+3]; \
+            type *out_row0 = out_rows[i+0], *out_row1 = out_rows[i+1]; \
+            type *out_row2 = out_rows[i+2], *out_row3 = out_rows[i+3]; \
+            for( int k = 0; k<w; ++k ) { \
+                for( int uv=1; uv<=2; ++uv ) { \
+                   out_row0[uv] = out_row2[uv] = (in_row0[uv]+in_row2[uv]+1)/2; \
+                   out_row1[uv] = out_row3[uv] = (in_row1[uv]+in_row3[uv]+1)/2; \
+                } \
+                in_row0 += components; in_row1 += components; \
+                in_row2 += components; in_row3 += components; \
+                out_row0 += components; out_row1 += components; \
+                out_row2 += components; out_row3 += components; \
+            } \
+        } \
+    } \
+ \
+    if( config.int_horizontal ) { \
+        if( config.inpainting ) { \
+            int kmax = w-7+config.offset; \
+            for( int i=0; i<h; ++i ) { \
+                type *in_row0 = in_rows[i+0], *out_row0 = output_rows[i+0]; \
+                for( int k=config.offset; k<kmax; k+=4 ) { \
+                    int k0 = (k+0) * components, a = in_row0[k0]; \
+                    int b, d = 0, k4 = (k+4) * components; \
+                    for( int jk=k0,n=4; --n>=0; a=b ) { \
+                        b = in_row0[jk+=components]; \
+                        d += a<b ? b-a : a-b;  d += config.bias; \
+                    } \
+                    if( d < config.thresh ) { \
+                        for( int jk=k0,n=4; --n>0; ) { \
+                            jk += components; \
+                            for( int uv=1; uv<=2; ++uv ) { \
+                                out_row0[jk+uv] = (n*in_row0[jk+uv] + (4-n)*in_row0[k4+uv]+2)/4; \
+                            } \
+                        } \
+                    } \
+                    else { \
+                        int t = 0;  a = in_row0[k0]; \
+                        for( int jk=k0,n=4; --n>0; a=b ) { \
+                            b = in_row0[jk+=components]; \
+                            t += a<b ? b-a : a-b;  t += config.bias; \
+                            for( int uv=1; uv<=2; ++uv ) { \
+                              out_row0[jk+uv] = (2*((d-t)*in_row0[k0+uv] + t*in_row0[k4+uv])+d)/(2*d); \
+                            } \
+                        } \
+                    } \
+                } \
+            } \
+        } \
+        else { \
+            int kmax = w-7+config.offset; \
+            for( int i=0; i<h; ++i ) { \
+                type *in_row0 = in_rows[i]; \
+                type *out_row0 = output_rows[i]; \
+                for( int k=config.offset; k<kmax; k+=4 ) { \
+                    for( int uv=1; uv<=2; ++uv ) { \
+                        int sum, avg, k0 = (k+0) * components, k4 = (k+4) * components; \
+                        sum  = in_row0[k0 + uv]; sum += in_row0[(k0+=components) + uv]; \
+                        sum += in_row0[k4 + uv]; sum += in_row0[(k4+=components) + uv]; \
+                        avg = (sum + 2) / 4; \
+                        out_row0[(k0+=components)+uv] = avg; \
+                        out_row0[(k0+=components)+uv] = avg; \
+                    } \
+                } \
+            } \
+        } \
+    } \
+}
+
+int yuv411Main::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
+{
+       load_configuration();
+       int w = input_ptr->get_w();
+       int h = input_ptr->get_h();
+       int colormodel = input_ptr->get_color_model();
+
+       if( input_ptr == output_ptr ||
+           ( config.avg_vertical && config.int_horizontal ) ) {
+               if( temp_frame && (temp_frame->get_color_model() != colormodel ||
+                   temp_frame->get_w() != w || temp_frame->get_h() != h) ) {
+                       delete temp_frame;
+                       temp_frame = 0;
+               }
+               if( !temp_frame )
+                       temp_frame = new VFrame(w, h, colormodel);
+               if( input_ptr == output_ptr ) {
+                       temp_frame->copy_from(input_ptr);
+                       input_ptr = temp_frame;
+               }
+       }
+
+       switch( colormodel ) {
+       case BC_YUV888:
+               YUV411_MACRO(unsigned char, 3);
+               break;
+       case BC_YUVA8888:
+               YUV411_MACRO(unsigned char, 4);
+               break;
+       }
+
+       if( this->colormodel != colormodel ) {
+               this->colormodel = colormodel;
+               send_render_gui(this);
+       }
+
+       return 0;
+}
+
+
+NEW_WINDOW_MACRO(yuv411Main, yuv411Window)
+
+LOAD_CONFIGURATION_MACRO(yuv411Main, yuv411Config)
+
+void yuv411Main::update_gui()
+{
+       if(thread)
+       {
+               load_configuration();
+               thread->window->lock_window();
+               yuv411Window *window = (yuv411Window *)thread->window;
+               window->update_enables();
+               window->avg_vertical->update((int)config.avg_vertical);
+               window->int_horizontal->update((int)config.int_horizontal);
+               window->inpainting->update((int)config.inpainting);
+               window->offset->update((int)config.offset);
+               window->thresh->update((int)config.thresh);
+               window->bias->update((int)config.bias);
+               window->unlock_window();
+       }
+}
+
+void yuv411Main::render_gui(void *data)
+{
+       if(thread) {
+               thread->window->lock_window();
+               yuv411Window *window = (yuv411Window *)thread->window;
+               yuv411Main *client = (yuv411Main *)data; 
+               switch( client->colormodel ) {
+               case BC_YUV888:
+               case BC_YUVA8888:
+                       window->show_warning(0);
+                       break;
+               default:
+                       window->show_warning(1);
+                       break;
+               }
+               window->unlock_window();
+       }
+}
+
+void yuv411Main::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+
+       output.tag.set_title("YUV411");
+       output.tag.set_property("OFFSET",config.offset);
+       output.tag.set_property("THRESH",config.thresh);
+       output.tag.set_property("BIAS",config.bias);
+       output.append_tag();
+       if(config.avg_vertical) {
+               output.tag.set_title("VERTICAL");
+               output.append_tag();
+       }
+       if(config.int_horizontal) {     
+               output.tag.set_title("HORIZONTAL");
+               output.append_tag();
+       }
+       if(config.inpainting ) {        
+               output.tag.set_title("INPAINTING");
+               output.append_tag();
+       }
+       output.terminate_string();
+}
+
+void yuv411Main::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+
+       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+       int result = 0;
+       config.avg_vertical = config.int_horizontal = 0;
+       config.inpainting = 0;
+       config.offset = 1;
+       config.thresh = 4;
+       config.bias = 1;
+
+       while(!(result = input.read_tag()) ) {
+               if( input.tag.title_is("YUV411") ) {
+                       config.offset = input.tag.get_property("OFFSET",config.offset);
+                       config.thresh = input.tag.get_property("THRESH",config.thresh);
+                       config.bias = input.tag.get_property("BIAS",config.bias);
+               }
+               else if(input.tag.title_is("VERTICAL")) {
+                       config.avg_vertical = 1;
+               }
+               else if(input.tag.title_is("HORIZONTAL")) {
+                       config.int_horizontal = 1;
+               }
+               else if(input.tag.title_is("INPAINTING")) {
+                       config.inpainting = 1;
+               }
+       }
+}
+
diff --git a/cinelerra-5.1/plugins/yuv411/yuv411.h b/cinelerra-5.1/plugins/yuv411/yuv411.h
new file mode 100644 (file)
index 0000000..8a4bb98
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef YUV411_H
+#define YUV411_H
+
+
+class yuv411Main;
+class yuv411Window;
+
+#include "filexml.h"
+#include "yuv411win.h"
+#include "guicast.h"
+#include "pluginvclient.h"
+
+class yuv411Config
+{
+public:
+       yuv411Config();
+       void copy_from(yuv411Config &that);
+       int equivalent(yuv411Config &that);
+       void interpolate(yuv411Config &prev, yuv411Config &next, 
+               long prev_frame, long next_frame, long current_frame);
+       int int_horizontal;
+       int avg_vertical;
+       int inpainting;
+       int offset;
+       int thresh;
+       int bias;
+};
+
+class yuv411Main : public PluginVClient
+{
+       VFrame *temp_frame;
+       int colormodel;
+       friend class yuv411Window;
+public:
+       yuv411Main(PluginServer *server);
+       ~yuv411Main();
+
+// required for all realtime plugins
+       PLUGIN_CLASS_MEMBERS(yuv411Config)
+
+       int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
+       int is_realtime();
+       void update_gui();
+       void render_gui(void *data);
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+};
+
+
+#endif
diff --git a/cinelerra-5.1/plugins/yuv411/yuv411win.C b/cinelerra-5.1/plugins/yuv411/yuv411win.C
new file mode 100644 (file)
index 0000000..65e8315
--- /dev/null
@@ -0,0 +1,152 @@
+#include "bcdisplayinfo.h"
+#include "yuv411win.h"
+#include "language.h"
+
+yuv411Window::yuv411Window(yuv411Main *client)
+ : PluginClientWindow(client, 250, 220, 250, 220, 0)
+{ 
+       this->client = client; 
+}
+
+yuv411Window::~yuv411Window()
+{
+}
+
+void yuv411Window::create_objects()
+{
+       int x = 10, y = 10, x1=90;
+       add_tool(avg_vertical = new yuv411Toggle(client, 
+               &(client->config.avg_vertical), 
+               _("Vertical average"),
+               x, 
+               y));
+       y += 30;
+       add_tool(int_horizontal = new yuv411Toggle(client, 
+               &(client->config.int_horizontal), 
+               _("Horizontal interpolate"),
+               x, 
+               y));
+       y += 30;
+       add_tool(inpainting = new yuv411Toggle(client, 
+               &(client->config.inpainting), 
+               _("Inpainting method"),
+               x, 
+               y));
+       y += 30;
+       add_subwindow(new BC_Title(x, y, _("Offset:")));
+       add_subwindow(offset=new yuv411Offset(client,x1,y));
+       y += 30;
+       add_subwindow(new BC_Title(x, y, _("Threshold:")));
+       add_subwindow(thresh=new yuv411Thresh(client,x1,y));
+       y += 30;
+       add_subwindow(new BC_Title(x, y, _("Bias:")));
+       add_subwindow(bias=new yuv411Bias(client,x1,y));
+       y += 30;
+       show_window();
+       flush();
+
+       yuv_warning = new BC_Title(x, y, _("Warning: colormodel not YUV"),MEDIUMFONT,RED);
+       add_subwindow(yuv_warning);
+       yuv_warning->hide_window();
+}
+
+int yuv411Window::close_event()
+{
+       set_done(1);
+       return 1;
+}
+
+yuv411Toggle::yuv411Toggle(yuv411Main *client, int *output, char *string, int x, int y)
+ : BC_CheckBox(x, y, *output, string)
+{
+       this->client = client;
+       this->output = output;
+}
+yuv411Toggle::~yuv411Toggle()
+{
+}
+int yuv411Toggle::handle_event()
+{
+       *output = get_value();
+       ((yuv411Window*)client->thread->window)->update_enables();
+       client->send_configure_change();
+       return 1;
+}
+
+yuv411Offset::yuv411Offset(yuv411Main *client, int x, int y)
+ :  BC_FSlider(x, y, 0, 100, 100, (float)0, (float)2,
+            (float)client->config.offset)
+{
+       this->client = client;
+       set_precision(1.0);
+}
+int yuv411Offset::handle_event()
+{
+       client->config.offset = get_value();
+       client->send_configure_change();
+       return 1;
+}
+
+yuv411Thresh::yuv411Thresh(yuv411Main *client, int x, int y)
+ :  BC_FSlider(x, y, 0, 100, 100, (float)1, (float)100,
+            (float)client->config.thresh)
+{
+       this->client = client;
+       set_precision(1.0);
+}
+int yuv411Thresh::handle_event()
+{
+       client->config.thresh = get_value();
+       client->send_configure_change();
+       return 1;
+}
+
+yuv411Bias::yuv411Bias(yuv411Main *client, int x, int y)
+ :  BC_FSlider(x, y, 0, 100, 100, (float)0, (float)25,
+            (float)client->config.bias)
+{
+       this->client = client;
+       set_precision(1.0);
+}
+
+int yuv411Bias::handle_event()
+{
+       client->config.bias = get_value();
+       client->send_configure_change();
+       return 1;
+}
+
+void yuv411Window::update_enables()
+{
+       yuv411Config &config = client->config;
+       if( !config.int_horizontal && config.inpainting ) {
+               config.inpainting = 0;
+               inpainting->set_value(0);
+       }
+       if( config.int_horizontal ) {
+               inpainting->enable();
+               offset->show_window();
+       }
+       else {
+               inpainting->disable();
+               offset->hide_window();
+       }
+       if( config.int_horizontal && config.inpainting ) {
+               thresh->show_window();
+               bias->show_window();
+       }
+       else {
+               thresh->hide_window();
+               bias->hide_window();
+       }
+}
+
+void yuv411Window::show_warning(int warn)
+{
+       if( warn )
+               yuv_warning->show_window();
+       else
+               yuv_warning->hide_window();
+}
+
+
diff --git a/cinelerra-5.1/plugins/yuv411/yuv411win.h b/cinelerra-5.1/plugins/yuv411/yuv411win.h
new file mode 100644 (file)
index 0000000..20388fc
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef YUV411WIN_H
+#define YUV411WIN_H
+
+#include "filexml.inc"
+#include "yuv411.h"
+#include "mutex.h"
+#include "pluginvclient.h"
+#include "bctitle.h"
+#include "colors.h"
+#include "fonts.h"
+
+class yuv411Toggle;
+class yuv411Offset;
+class yuv411Thresh;
+class yuv411Bias;
+
+class yuv411Window : public PluginClientWindow
+{
+public:
+       yuv411Window(yuv411Main *client);
+       ~yuv411Window();
+       
+       void create_objects();
+       int close_event();
+       void update_enables();
+       void show_warning(int warn);
+       
+       yuv411Main *client;
+       yuv411Toggle *avg_vertical;
+       yuv411Toggle *int_horizontal;
+       yuv411Toggle *inpainting;
+       yuv411Offset *offset;
+       yuv411Thresh *thresh;
+       yuv411Bias *bias;
+       BC_Title *yuv_warning;
+};
+
+class yuv411Toggle : public BC_CheckBox
+{
+public:
+       yuv411Toggle(yuv411Main *client, int *output, char *string, int x, int y);
+       ~yuv411Toggle();
+       int handle_event();
+
+       yuv411Main *client;
+       int *output;
+};
+
+class yuv411Offset : public BC_FSlider
+{
+public:
+       yuv411Offset(yuv411Main *client, int x, int y);
+       int handle_event();
+       yuv411Main *client;
+};
+
+class yuv411Thresh : public BC_FSlider
+{
+public:
+       yuv411Thresh(yuv411Main *client, int x, int y);
+       int handle_event();
+       yuv411Main *client;
+};
+
+class yuv411Bias : public BC_FSlider
+{
+public:
+       yuv411Bias(yuv411Main *client, int x, int y);
+       int handle_event();
+       yuv411Main *client;
+};
+
+#endif