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 "picon_png.h"
29
#include "pluginvclient.h"
43
class ShiftInterlaceWindow;
44
class ShiftInterlaceMain;
46
class ShiftInterlaceConfig
49
ShiftInterlaceConfig();
51
int equivalent(ShiftInterlaceConfig &that);
52
void copy_from(ShiftInterlaceConfig &that);
53
void interpolate(ShiftInterlaceConfig &prev,
54
ShiftInterlaceConfig &next,
65
class ShiftInterlaceOdd : public BC_ISlider
68
ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y);
70
ShiftInterlaceMain *plugin;
73
class ShiftInterlaceEven : public BC_ISlider
76
ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y);
78
ShiftInterlaceMain *plugin;
81
class ShiftInterlaceWindow : public BC_Window
84
ShiftInterlaceWindow(ShiftInterlaceMain *plugin, int x, int y);
86
void create_objects();
89
ShiftInterlaceOdd *odd_offset;
90
ShiftInterlaceEven *even_offset;
91
ShiftInterlaceMain *plugin;
95
PLUGIN_THREAD_HEADER(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
100
class ShiftInterlaceMain : public PluginVClient
103
ShiftInterlaceMain(PluginServer *server);
104
~ShiftInterlaceMain();
106
// required for all realtime plugins
107
int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
109
char* plugin_title();
115
void save_data(KeyFrame *keyframe);
116
void read_data(KeyFrame *keyframe);
117
int load_configuration();
122
void shift_row(VFrame *input_frame,
123
VFrame *output_frame,
130
ShiftInterlaceConfig config;
131
ShiftInterlaceThread *thread;
138
PluginClient* new_plugin(PluginServer *server)
140
return new ShiftInterlaceMain(server);
146
ShiftInterlaceConfig::ShiftInterlaceConfig()
153
int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
155
return (odd_offset == that.odd_offset &&
156
even_offset == that.even_offset);
159
void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
161
odd_offset = that.odd_offset;
162
even_offset = that.even_offset;
165
void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
166
ShiftInterlaceConfig &next,
171
double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
172
double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
174
this->odd_offset = (int)(prev.odd_offset * prev_scale + next.odd_offset * next_scale);
175
this->even_offset = (int)(prev.even_offset * prev_scale + next.even_offset * next_scale);
183
ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin,
186
: BC_Window(plugin->gui_string,
197
this->plugin = plugin;
201
void ShiftInterlaceWindow::create_objects()
206
add_subwindow(new BC_Title(x, y, _("Odd offset:")));
207
add_subwindow(odd_offset = new ShiftInterlaceOdd(plugin, x + 90, y));
209
add_subwindow(new BC_Title(x, y, _("Even offset:")));
210
add_subwindow(even_offset = new ShiftInterlaceEven(plugin, x + 90, y));
216
WINDOW_CLOSE_EVENT(ShiftInterlaceWindow)
218
ShiftInterlaceOdd::ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y)
226
plugin->config.odd_offset)
228
this->plugin = plugin;
230
int ShiftInterlaceOdd::handle_event()
232
plugin->config.odd_offset = get_value();
233
plugin->send_configure_change();
240
ShiftInterlaceEven::ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y)
248
plugin->config.even_offset)
250
this->plugin = plugin;
254
int ShiftInterlaceEven::handle_event()
256
plugin->config.even_offset = get_value();
257
plugin->send_configure_change();
268
PLUGIN_THREAD_OBJECT(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
272
ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
273
: PluginVClient(server)
275
PLUGIN_CONSTRUCTOR_MACRO
278
ShiftInterlaceMain::~ShiftInterlaceMain()
280
PLUGIN_DESTRUCTOR_MACRO
284
char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
285
int ShiftInterlaceMain::is_realtime() { return 1; }
288
SHOW_GUI_MACRO(ShiftInterlaceMain, ShiftInterlaceThread)
290
NEW_PICON_MACRO(ShiftInterlaceMain)
292
SET_STRING_MACRO(ShiftInterlaceMain)
294
LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
296
RAISE_WINDOW_MACRO(ShiftInterlaceMain)
299
int ShiftInterlaceMain::load_defaults()
301
char directory[1024], string[1024];
302
// set the default directory
303
sprintf(directory, "%sshiftinterlace.rc", BCASTDIR);
306
defaults = new BC_Hash(directory);
309
config.odd_offset = defaults->get("ODD_OFFSET", config.odd_offset);
310
config.even_offset = defaults->get("EVEN_OFFSET", config.even_offset);
314
int ShiftInterlaceMain::save_defaults()
316
defaults->update("ODD_OFFSET", config.odd_offset);
317
defaults->update("EVEN_OFFSET", config.even_offset);
322
void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
326
// cause data to be stored directly in text
327
output.set_shared_string(keyframe->data, MESSAGESIZE);
328
output.tag.set_title("SHIFTINTERLACE");
329
output.tag.set_property("ODD_OFFSET", config.odd_offset);
330
output.tag.set_property("EVEN_OFFSET", config.even_offset);
332
output.tag.set_title("/SHIFTINTERLACE");
334
output.append_newline();
335
output.terminate_string();
336
// data is now in *text
339
void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
343
input.set_shared_string(keyframe->data, strlen(keyframe->data));
349
result = input.read_tag();
353
if(input.tag.title_is("SHIFTINTERLACE"))
355
config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
356
config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
362
void ShiftInterlaceMain::update_gui()
366
load_configuration();
367
thread->window->lock_window();
368
thread->window->odd_offset->update(config.odd_offset);
369
thread->window->even_offset->update(config.even_offset);
370
thread->window->unlock_window();
375
#define SHIFT_ROW_MACRO(components, type, chroma_offset) \
377
type *input_row = (type*)input_frame->get_rows()[row]; \
378
type *output_row = (type*)output_frame->get_rows()[row]; \
383
for(i = 0, j = -offset; \
387
output_row[i * components + 0] = input_row[j * components + 0]; \
388
output_row[i * components + 1] = input_row[j * components + 1]; \
389
output_row[i * components + 2] = input_row[j * components + 2]; \
390
if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
395
output_row[i * components + 0] = 0; \
396
output_row[i * components + 1] = chroma_offset; \
397
output_row[i * components + 2] = chroma_offset; \
398
if(components == 4) output_row[i * components + 3] = 0; \
404
for(i = w - offset - 1, j = w - 1; \
409
output_row[j * components + 0] = input_row[i * components + 0]; \
410
output_row[j * components + 1] = input_row[i * components + 1]; \
411
output_row[j * components + 2] = input_row[i * components + 2]; \
412
if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
415
for( ; j >= 0; j--) \
417
output_row[j * components + 0] = 0; \
418
output_row[j * components + 1] = chroma_offset; \
419
output_row[j * components + 2] = chroma_offset; \
420
if(components == 4) output_row[j * components + 3] = 0; \
426
void ShiftInterlaceMain::shift_row(VFrame *input_frame,
427
VFrame *output_frame,
431
int w = input_frame->get_w();
432
switch(input_frame->get_color_model())
435
SHIFT_ROW_MACRO(3, unsigned char, 0x0)
438
SHIFT_ROW_MACRO(3, float, 0x0)
441
SHIFT_ROW_MACRO(3, unsigned char, 0x80)
444
SHIFT_ROW_MACRO(4, float, 0x0)
447
SHIFT_ROW_MACRO(4, unsigned char, 0x0)
450
SHIFT_ROW_MACRO(4, unsigned char, 0x80)
453
SHIFT_ROW_MACRO(3, uint16_t, 0x0)
456
SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
458
case BC_RGBA16161616:
459
SHIFT_ROW_MACRO(4, uint16_t, 0x0)
461
case BC_YUVA16161616:
462
SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
467
int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
469
load_configuration();
471
int h = input_ptr->get_h();
472
for(int i = 0; i < h; i++)
475
shift_row(input_ptr, output_ptr, config.even_offset, i);
477
shift_row(input_ptr, output_ptr, config.odd_offset, i);