4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcdisplayinfo.h"
28 #include "pluginvclient.h"
42 class ShiftInterlaceWindow;
43 class ShiftInterlaceMain;
45 class ShiftInterlaceConfig
48 ShiftInterlaceConfig();
50 int equivalent(ShiftInterlaceConfig &that);
51 void copy_from(ShiftInterlaceConfig &that);
52 void interpolate(ShiftInterlaceConfig &prev,
53 ShiftInterlaceConfig &next,
64 class ShiftInterlaceOdd : public BC_ISlider
67 ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y);
69 ShiftInterlaceMain *plugin;
72 class ShiftInterlaceEven : public BC_ISlider
75 ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y);
77 ShiftInterlaceMain *plugin;
80 class ShiftInterlaceWindow : public PluginClientWindow
83 ShiftInterlaceWindow(ShiftInterlaceMain *plugin);
85 void create_objects();
87 ShiftInterlaceOdd *odd_offset;
88 ShiftInterlaceEven *even_offset;
89 ShiftInterlaceMain *plugin;
97 class ShiftInterlaceMain : public PluginVClient
100 ShiftInterlaceMain(PluginServer *server);
101 ~ShiftInterlaceMain();
103 // required for all realtime plugins
104 PLUGIN_CLASS_MEMBERS(ShiftInterlaceConfig)
105 int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
108 void save_data(KeyFrame *keyframe);
109 void read_data(KeyFrame *keyframe);
112 void shift_row(VFrame *input_frame,
113 VFrame *output_frame,
123 PluginClient* new_plugin(PluginServer *server)
125 return new ShiftInterlaceMain(server);
131 ShiftInterlaceConfig::ShiftInterlaceConfig()
138 int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
140 return (odd_offset == that.odd_offset &&
141 even_offset == that.even_offset);
144 void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
146 odd_offset = that.odd_offset;
147 even_offset = that.even_offset;
150 void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
151 ShiftInterlaceConfig &next,
156 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
157 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
159 this->odd_offset = (int)(prev.odd_offset * prev_scale + next.odd_offset * next_scale);
160 this->even_offset = (int)(prev.even_offset * prev_scale + next.even_offset * next_scale);
168 ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin)
169 : PluginClientWindow(plugin,
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));
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();
250 ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
251 : PluginVClient(server)
256 ShiftInterlaceMain::~ShiftInterlaceMain()
262 const char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
263 int ShiftInterlaceMain::is_realtime() { return 1; }
269 LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
271 NEW_WINDOW_MACRO(ShiftInterlaceMain, ShiftInterlaceWindow)
275 void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
279 // cause data to be stored directly in text
280 output.set_shared_output(keyframe->xbuf);
281 output.tag.set_title("SHIFTINTERLACE");
282 output.tag.set_property("ODD_OFFSET", config.odd_offset);
283 output.tag.set_property("EVEN_OFFSET", config.even_offset);
285 output.tag.set_title("/SHIFTINTERLACE");
287 output.append_newline();
288 output.terminate_string();
289 // data is now in *text
292 void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
296 input.set_shared_input(keyframe->xbuf);
302 result = input.read_tag();
306 if(input.tag.title_is("SHIFTINTERLACE"))
308 config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
309 config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
315 void ShiftInterlaceMain::update_gui()
319 load_configuration();
320 thread->window->lock_window();
321 ((ShiftInterlaceWindow*)thread->window)->odd_offset->update(config.odd_offset);
322 ((ShiftInterlaceWindow*)thread->window)->even_offset->update(config.even_offset);
323 thread->window->unlock_window();
328 #define SHIFT_ROW_MACRO(components, type, chroma_offset) \
330 type *input_row = (type*)input_frame->get_rows()[row]; \
331 type *output_row = (type*)output_frame->get_rows()[row]; \
336 for(i = 0, j = -offset; \
340 output_row[i * components + 0] = input_row[j * components + 0]; \
341 output_row[i * components + 1] = input_row[j * components + 1]; \
342 output_row[i * components + 2] = input_row[j * components + 2]; \
343 if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
348 output_row[i * components + 0] = 0; \
349 output_row[i * components + 1] = chroma_offset; \
350 output_row[i * components + 2] = chroma_offset; \
351 if(components == 4) output_row[i * components + 3] = 0; \
357 for(i = w - offset - 1, j = w - 1; \
362 output_row[j * components + 0] = input_row[i * components + 0]; \
363 output_row[j * components + 1] = input_row[i * components + 1]; \
364 output_row[j * components + 2] = input_row[i * components + 2]; \
365 if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
368 for( ; j >= 0; j--) \
370 output_row[j * components + 0] = 0; \
371 output_row[j * components + 1] = chroma_offset; \
372 output_row[j * components + 2] = chroma_offset; \
373 if(components == 4) output_row[j * components + 3] = 0; \
379 void ShiftInterlaceMain::shift_row(VFrame *input_frame,
380 VFrame *output_frame,
384 int w = input_frame->get_w();
385 switch(input_frame->get_color_model())
388 SHIFT_ROW_MACRO(3, unsigned char, 0x0)
391 SHIFT_ROW_MACRO(3, float, 0x0)
394 SHIFT_ROW_MACRO(3, unsigned char, 0x80)
397 SHIFT_ROW_MACRO(4, float, 0x0)
400 SHIFT_ROW_MACRO(4, unsigned char, 0x0)
403 SHIFT_ROW_MACRO(4, unsigned char, 0x80)
406 SHIFT_ROW_MACRO(3, uint16_t, 0x0)
409 SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
411 case BC_RGBA16161616:
412 SHIFT_ROW_MACRO(4, uint16_t, 0x0)
414 case BC_YUVA16161616:
415 SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
420 int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
422 load_configuration();
424 int h = input_ptr->get_h();
425 for(int i = 0; i < h; i++)
428 shift_row(input_ptr, output_ptr, config.even_offset, i);
430 shift_row(input_ptr, output_ptr, config.odd_offset, i);