1 #include "bcdisplayinfo.h"
8 #include "plugincolors.h"
9 #include "pluginvclient.h"
17 class InvertVideoEffect;
20 class InvertVideoConfig
25 void copy_from(InvertVideoConfig &src);
26 int equivalent(InvertVideoConfig &src);
27 void interpolate(InvertVideoConfig &prev,
28 InvertVideoConfig &next,
36 class InvertVideoEnable : public BC_CheckBox
39 InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text);
41 InvertVideoEffect *plugin;
45 class InvertVideoWindow : public BC_Window
48 InvertVideoWindow(InvertVideoEffect *plugin, int x, int y);
49 void create_objects();
51 InvertVideoEnable *r, *g, *b, *a;
52 InvertVideoEffect *plugin;
55 PLUGIN_THREAD_HEADER(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
57 class InvertVideoEffect : public PluginVClient
60 InvertVideoEffect(PluginServer *server);
62 int process_buffer(VFrame *frame,
63 int64_t start_position,
70 void save_data(KeyFrame *keyframe);
71 void read_data(KeyFrame *keyframe);
76 int load_configuration();
79 InvertVideoConfig config;
80 InvertVideoThread *thread;
88 REGISTER_PLUGIN(InvertVideoEffect)
96 InvertVideoConfig::InvertVideoConfig()
104 void InvertVideoConfig::copy_from(InvertVideoConfig &src)
112 int InvertVideoConfig::equivalent(InvertVideoConfig &src)
120 void InvertVideoConfig::interpolate(InvertVideoConfig &prev,
121 InvertVideoConfig &next,
135 InvertVideoEnable::InvertVideoEnable(InvertVideoEffect *plugin, int *output, int x, int y, char *text)
136 : BC_CheckBox(x, y, *output, text)
138 this->plugin = plugin;
139 this->output = output;
141 int InvertVideoEnable::handle_event()
143 *output = get_value();
144 plugin->send_configure_change();
152 InvertVideoWindow::InvertVideoWindow(InvertVideoEffect *plugin, int x, int y)
153 : BC_Window(plugin->gui_string,
164 this->plugin = plugin;
167 void InvertVideoWindow::create_objects()
170 add_subwindow(r = new InvertVideoEnable(plugin, &plugin->config.r, x, y, _("Invert R")));
172 add_subwindow(g = new InvertVideoEnable(plugin, &plugin->config.g, x, y, _("Invert G")));
174 add_subwindow(b = new InvertVideoEnable(plugin, &plugin->config.b, x, y, _("Invert B")));
176 add_subwindow(a = new InvertVideoEnable(plugin, &plugin->config.a, x, y, _("Invert A")));
182 WINDOW_CLOSE_EVENT(InvertVideoWindow)
188 PLUGIN_THREAD_OBJECT(InvertVideoEffect, InvertVideoThread, InvertVideoWindow)
195 InvertVideoEffect::InvertVideoEffect(PluginServer *server)
196 : PluginVClient(server)
198 PLUGIN_CONSTRUCTOR_MACRO
200 InvertVideoEffect::~InvertVideoEffect()
202 PLUGIN_DESTRUCTOR_MACRO
205 char* InvertVideoEffect::plugin_title() { return N_("Invert Video"); }
206 int InvertVideoEffect::is_realtime() { return 1; }
208 NEW_PICON_MACRO(InvertVideoEffect)
209 SHOW_GUI_MACRO(InvertVideoEffect, InvertVideoThread)
210 RAISE_WINDOW_MACRO(InvertVideoEffect)
211 SET_STRING_MACRO(InvertVideoEffect)
212 LOAD_CONFIGURATION_MACRO(InvertVideoEffect, InvertVideoConfig)
214 void InvertVideoEffect::update_gui()
218 thread->window->lock_window();
219 load_configuration();
220 thread->window->r->update(config.r);
221 thread->window->g->update(config.g);
222 thread->window->b->update(config.b);
223 thread->window->a->update(config.a);
224 thread->window->unlock_window();
228 int InvertVideoEffect::load_defaults()
230 char directory[BCTEXTLEN];
231 sprintf(directory, "%sinvertvideo.rc", BCASTDIR);
232 defaults = new BC_Hash(directory);
234 config.r = defaults->get("R", config.r);
235 config.g = defaults->get("G", config.g);
236 config.b = defaults->get("B", config.b);
237 config.a = defaults->get("A", config.a);
241 int InvertVideoEffect::save_defaults()
243 defaults->update("R", config.r);
244 defaults->update("G", config.g);
245 defaults->update("B", config.b);
246 defaults->update("A", config.a);
251 void InvertVideoEffect::save_data(KeyFrame *keyframe)
254 output.set_shared_string(keyframe->data, MESSAGESIZE);
255 output.tag.set_title("INVERTVIDEO");
256 output.tag.set_property("R", config.r);
257 output.tag.set_property("G", config.g);
258 output.tag.set_property("B", config.b);
259 output.tag.set_property("A", config.a);
261 output.tag.set_title("/INVERTVIDEO");
263 output.terminate_string();
266 void InvertVideoEffect::read_data(KeyFrame *keyframe)
269 input.set_shared_string(keyframe->data, strlen(keyframe->data));
270 while(!input.read_tag())
272 if(input.tag.title_is("INVERTVIDEO"))
274 config.r = input.tag.get_property("R", config.r);
275 config.g = input.tag.get_property("G", config.g);
276 config.b = input.tag.get_property("B", config.b);
277 config.a = input.tag.get_property("A", config.a);
283 #define INVERT_MACRO(type, components, max) \
285 for(int i = 0; i < frame->get_h(); i++) \
287 type *in_row = (type*)frame->get_rows()[i]; \
288 type *out_row = (type*)frame->get_rows()[i]; \
290 for(int j = 0; j < w; j++) \
292 if(config.r) out_row[0] = max - in_row[0]; \
293 if(config.g) out_row[1] = max - in_row[1]; \
294 if(config.b) out_row[2] = max - in_row[2]; \
295 if(components == 4) \
296 if(config.a) out_row[3] = max - in_row[3]; \
298 in_row += components; \
299 out_row += components; \
304 int InvertVideoEffect::process_buffer(VFrame *frame,
305 int64_t start_position,
308 load_configuration();
317 if(config.r || config.g || config.b || config.a)
324 int w = frame->get_w();
326 switch(frame->get_color_model())
329 INVERT_MACRO(float, 3, 1.0)
333 INVERT_MACRO(unsigned char, 3, 0xff)
336 INVERT_MACRO(float, 4, 1.0)
340 INVERT_MACRO(unsigned char, 4, 0xff)
344 INVERT_MACRO(uint16_t, 3, 0xffff)
346 case BC_RGBA16161616:
347 case BC_YUVA16161616:
348 INVERT_MACRO(uint16_t, 4, 0xffff)
356 int InvertVideoEffect::handle_opengl()
359 static char *invert_frag =
360 "uniform sampler2D tex;\n"
361 "uniform bool do_r;\n"
362 "uniform bool do_g;\n"
363 "uniform bool do_b;\n"
364 "uniform bool do_a;\n"
367 " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
368 " if(do_r) gl_FragColor.r = 1.0 - gl_FragColor.r;\n"
369 " if(do_g) gl_FragColor.g = 1.0 - gl_FragColor.g;\n"
370 " if(do_b) gl_FragColor.b = 1.0 - gl_FragColor.b;\n"
371 " if(do_a) gl_FragColor.a = 1.0 - gl_FragColor.a;\n"
374 get_output()->to_texture();
375 get_output()->enable_opengl();
377 unsigned int frag_shader = 0;
378 frag_shader = VFrame::make_shader(0,
381 glUseProgram(frag_shader);
382 glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
383 glUniform1i(glGetUniformLocation(frag_shader, "do_r"), config.r);
384 glUniform1i(glGetUniformLocation(frag_shader, "do_g"), config.g);
385 glUniform1i(glGetUniformLocation(frag_shader, "do_b"), config.b);
386 glUniform1i(glGetUniformLocation(frag_shader, "do_a"), config.a);
389 VFrame::init_screen(get_output()->get_w(), get_output()->get_h());
390 get_output()->bind_texture(0);
391 get_output()->draw_texture();
393 get_output()->set_opengl_state(VFrame::SCREEN);