1 #include "bcdisplayinfo.h"
8 #include "pluginvclient.h"
22 class ShiftInterlaceWindow;
23 class ShiftInterlaceMain;
25 class ShiftInterlaceConfig
28 ShiftInterlaceConfig();
30 int equivalent(ShiftInterlaceConfig &that);
31 void copy_from(ShiftInterlaceConfig &that);
32 void interpolate(ShiftInterlaceConfig &prev,
33 ShiftInterlaceConfig &next,
44 class ShiftInterlaceOdd : public BC_ISlider
47 ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y);
49 ShiftInterlaceMain *plugin;
52 class ShiftInterlaceEven : public BC_ISlider
55 ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y);
57 ShiftInterlaceMain *plugin;
60 class ShiftInterlaceWindow : public BC_Window
63 ShiftInterlaceWindow(ShiftInterlaceMain *plugin, int x, int y);
65 void create_objects();
68 ShiftInterlaceOdd *odd_offset;
69 ShiftInterlaceEven *even_offset;
70 ShiftInterlaceMain *plugin;
74 PLUGIN_THREAD_HEADER(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
79 class ShiftInterlaceMain : public PluginVClient
82 ShiftInterlaceMain(PluginServer *server);
83 ~ShiftInterlaceMain();
85 // required for all realtime plugins
86 int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
94 void save_data(KeyFrame *keyframe);
95 void read_data(KeyFrame *keyframe);
96 int load_configuration();
101 void shift_row(VFrame *input_frame,
102 VFrame *output_frame,
109 ShiftInterlaceConfig config;
110 ShiftInterlaceThread *thread;
117 PluginClient* new_plugin(PluginServer *server)
119 return new ShiftInterlaceMain(server);
125 ShiftInterlaceConfig::ShiftInterlaceConfig()
132 int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
134 return (odd_offset == that.odd_offset &&
135 even_offset == that.even_offset);
138 void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
140 odd_offset = that.odd_offset;
141 even_offset = that.even_offset;
144 void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
145 ShiftInterlaceConfig &next,
150 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
151 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
153 this->odd_offset = (int)(prev.odd_offset * prev_scale + next.odd_offset * next_scale);
154 this->even_offset = (int)(prev.even_offset * prev_scale + next.even_offset * next_scale);
162 ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin,
165 : BC_Window(plugin->gui_string,
176 this->plugin = plugin;
180 void ShiftInterlaceWindow::create_objects()
185 add_subwindow(new BC_Title(x, y, _("Odd offset:")));
186 add_subwindow(odd_offset = new ShiftInterlaceOdd(plugin, x + 90, y));
188 add_subwindow(new BC_Title(x, y, _("Even offset:")));
189 add_subwindow(even_offset = new ShiftInterlaceEven(plugin, x + 90, y));
195 WINDOW_CLOSE_EVENT(ShiftInterlaceWindow)
197 ShiftInterlaceOdd::ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y)
205 plugin->config.odd_offset)
207 this->plugin = plugin;
209 int ShiftInterlaceOdd::handle_event()
211 plugin->config.odd_offset = get_value();
212 plugin->send_configure_change();
219 ShiftInterlaceEven::ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y)
227 plugin->config.even_offset)
229 this->plugin = plugin;
233 int ShiftInterlaceEven::handle_event()
235 plugin->config.even_offset = get_value();
236 plugin->send_configure_change();
247 PLUGIN_THREAD_OBJECT(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
251 ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
252 : PluginVClient(server)
254 PLUGIN_CONSTRUCTOR_MACRO
257 ShiftInterlaceMain::~ShiftInterlaceMain()
259 PLUGIN_DESTRUCTOR_MACRO
263 char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
264 int ShiftInterlaceMain::is_realtime() { return 1; }
267 SHOW_GUI_MACRO(ShiftInterlaceMain, ShiftInterlaceThread)
269 NEW_PICON_MACRO(ShiftInterlaceMain)
271 SET_STRING_MACRO(ShiftInterlaceMain)
273 LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
275 RAISE_WINDOW_MACRO(ShiftInterlaceMain)
278 int ShiftInterlaceMain::load_defaults()
280 char directory[1024], string[1024];
281 // set the default directory
282 sprintf(directory, "%sshiftinterlace.rc", BCASTDIR);
285 defaults = new BC_Hash(directory);
288 config.odd_offset = defaults->get("ODD_OFFSET", config.odd_offset);
289 config.even_offset = defaults->get("EVEN_OFFSET", config.even_offset);
293 int ShiftInterlaceMain::save_defaults()
295 defaults->update("ODD_OFFSET", config.odd_offset);
296 defaults->update("EVEN_OFFSET", config.even_offset);
301 void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
305 // cause data to be stored directly in text
306 output.set_shared_string(keyframe->data, MESSAGESIZE);
307 output.tag.set_title("SHIFTINTERLACE");
308 output.tag.set_property("ODD_OFFSET", config.odd_offset);
309 output.tag.set_property("EVEN_OFFSET", config.even_offset);
311 output.append_newline();
312 output.terminate_string();
313 // data is now in *text
316 void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
320 input.set_shared_string(keyframe->data, strlen(keyframe->data));
326 result = input.read_tag();
330 if(input.tag.title_is("SHIFTINTERLACE"))
332 config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
333 config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
339 void ShiftInterlaceMain::update_gui()
343 load_configuration();
344 thread->window->lock_window();
345 thread->window->odd_offset->update(config.odd_offset);
346 thread->window->even_offset->update(config.even_offset);
347 thread->window->unlock_window();
352 #define SHIFT_ROW_MACRO(components, type, chroma_offset) \
354 type *input_row = (type*)input_frame->get_rows()[row]; \
355 type *output_row = (type*)output_frame->get_rows()[row]; \
360 for(i = 0, j = -offset; \
364 output_row[i * components + 0] = input_row[j * components + 0]; \
365 output_row[i * components + 1] = input_row[j * components + 1]; \
366 output_row[i * components + 2] = input_row[j * components + 2]; \
367 if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
372 output_row[i * components + 0] = 0; \
373 output_row[i * components + 1] = chroma_offset; \
374 output_row[i * components + 2] = chroma_offset; \
375 if(components == 4) output_row[i * components + 3] = 0; \
381 for(i = w - offset - 1, j = w - 1; \
386 output_row[j * components + 0] = input_row[i * components + 0]; \
387 output_row[j * components + 1] = input_row[i * components + 1]; \
388 output_row[j * components + 2] = input_row[i * components + 2]; \
389 if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
392 for( ; j >= 0; j--) \
394 output_row[j * components + 0] = 0; \
395 output_row[j * components + 1] = chroma_offset; \
396 output_row[j * components + 2] = chroma_offset; \
397 if(components == 4) output_row[j * components + 3] = 0; \
403 void ShiftInterlaceMain::shift_row(VFrame *input_frame,
404 VFrame *output_frame,
408 int w = input_frame->get_w();
409 switch(input_frame->get_color_model())
412 SHIFT_ROW_MACRO(3, unsigned char, 0x0)
415 SHIFT_ROW_MACRO(3, float, 0x0)
418 SHIFT_ROW_MACRO(3, unsigned char, 0x80)
421 SHIFT_ROW_MACRO(4, float, 0x0)
424 SHIFT_ROW_MACRO(4, unsigned char, 0x0)
427 SHIFT_ROW_MACRO(4, unsigned char, 0x80)
430 SHIFT_ROW_MACRO(3, uint16_t, 0x0)
433 SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
435 case BC_RGBA16161616:
436 SHIFT_ROW_MACRO(4, uint16_t, 0x0)
438 case BC_YUVA16161616:
439 SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
444 int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
446 load_configuration();
448 int h = input_ptr->get_h();
449 for(int i = 0; i < h; i++)
452 shift_row(input_ptr, output_ptr, config.even_offset, i);
454 shift_row(input_ptr, output_ptr, config.odd_offset, i);