00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "language.h"
00007 #include "picon_png.h"
00008 #include "pluginvclient.h"
00009 #include "vframe.h"
00010
00011
00012
00013 #include <stdint.h>
00014 #include <string.h>
00015
00016
00017
00018
00019
00020
00021
00022 class ShiftInterlaceWindow;
00023 class ShiftInterlaceMain;
00024
00025 class ShiftInterlaceConfig
00026 {
00027 public:
00028 ShiftInterlaceConfig();
00029
00030 int equivalent(ShiftInterlaceConfig &that);
00031 void copy_from(ShiftInterlaceConfig &that);
00032 void interpolate(ShiftInterlaceConfig &prev,
00033 ShiftInterlaceConfig &next,
00034 long prev_frame,
00035 long next_frame,
00036 long current_frame);
00037
00038
00039 int odd_offset;
00040 int even_offset;
00041 };
00042
00043
00044 class ShiftInterlaceOdd : public BC_ISlider
00045 {
00046 public:
00047 ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y);
00048 int handle_event();
00049 ShiftInterlaceMain *plugin;
00050 };
00051
00052 class ShiftInterlaceEven : public BC_ISlider
00053 {
00054 public:
00055 ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y);
00056 int handle_event();
00057 ShiftInterlaceMain *plugin;
00058 };
00059
00060 class ShiftInterlaceWindow : public BC_Window
00061 {
00062 public:
00063 ShiftInterlaceWindow(ShiftInterlaceMain *plugin, int x, int y);
00064
00065 void create_objects();
00066 int close_event();
00067
00068 ShiftInterlaceOdd *odd_offset;
00069 ShiftInterlaceEven *even_offset;
00070 ShiftInterlaceMain *plugin;
00071 };
00072
00073
00074 PLUGIN_THREAD_HEADER(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
00075
00076
00077
00078
00079 class ShiftInterlaceMain : public PluginVClient
00080 {
00081 public:
00082 ShiftInterlaceMain(PluginServer *server);
00083 ~ShiftInterlaceMain();
00084
00085
00086 int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
00087 int is_realtime();
00088 char* plugin_title();
00089 VFrame* new_picon();
00090 int show_gui();
00091 void raise_window();
00092 void update_gui();
00093 int set_string();
00094 void save_data(KeyFrame *keyframe);
00095 void read_data(KeyFrame *keyframe);
00096 int load_configuration();
00097 int load_defaults();
00098 int save_defaults();
00099
00100
00101 void shift_row(VFrame *input_frame,
00102 VFrame *output_frame,
00103 int offset,
00104 int row);
00105
00106
00107
00108
00109 ShiftInterlaceConfig config;
00110 ShiftInterlaceThread *thread;
00111 BC_Hash *defaults;
00112 };
00113
00114
00115
00116
00117 PluginClient* new_plugin(PluginServer *server)
00118 {
00119 return new ShiftInterlaceMain(server);
00120 }
00121
00122
00123
00124
00125 ShiftInterlaceConfig::ShiftInterlaceConfig()
00126 {
00127 odd_offset = 0;
00128 even_offset = 0;
00129 }
00130
00131
00132 int ShiftInterlaceConfig::equivalent(ShiftInterlaceConfig &that)
00133 {
00134 return (odd_offset == that.odd_offset &&
00135 even_offset == that.even_offset);
00136 }
00137
00138 void ShiftInterlaceConfig::copy_from(ShiftInterlaceConfig &that)
00139 {
00140 odd_offset = that.odd_offset;
00141 even_offset = that.even_offset;
00142 }
00143
00144 void ShiftInterlaceConfig::interpolate(ShiftInterlaceConfig &prev,
00145 ShiftInterlaceConfig &next,
00146 long prev_frame,
00147 long next_frame,
00148 long current_frame)
00149 {
00150 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00151 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00152
00153 this->odd_offset = (int)(prev.odd_offset * prev_scale + next.odd_offset * next_scale);
00154 this->even_offset = (int)(prev.even_offset * prev_scale + next.even_offset * next_scale);
00155 }
00156
00157
00158
00159
00160
00161
00162 ShiftInterlaceWindow::ShiftInterlaceWindow(ShiftInterlaceMain *plugin,
00163 int x,
00164 int y)
00165 : BC_Window(plugin->gui_string,
00166 x,
00167 y,
00168 310,
00169 100,
00170 310,
00171 100,
00172 0,
00173 0,
00174 1)
00175 {
00176 this->plugin = plugin;
00177 }
00178
00179
00180 void ShiftInterlaceWindow::create_objects()
00181 {
00182 int x = 10, y = 10;
00183 int margin = 30;
00184
00185 add_subwindow(new BC_Title(x, y, _("Odd offset:")));
00186 add_subwindow(odd_offset = new ShiftInterlaceOdd(plugin, x + 90, y));
00187 y += margin;
00188 add_subwindow(new BC_Title(x, y, _("Even offset:")));
00189 add_subwindow(even_offset = new ShiftInterlaceEven(plugin, x + 90, y));
00190
00191 show_window();
00192 flush();
00193 }
00194
00195 WINDOW_CLOSE_EVENT(ShiftInterlaceWindow)
00196
00197 ShiftInterlaceOdd::ShiftInterlaceOdd(ShiftInterlaceMain *plugin, int x, int y)
00198 : BC_ISlider(x,
00199 y,
00200 0,
00201 200,
00202 200,
00203 -100,
00204 100,
00205 plugin->config.odd_offset)
00206 {
00207 this->plugin = plugin;
00208 }
00209 int ShiftInterlaceOdd::handle_event()
00210 {
00211 plugin->config.odd_offset = get_value();
00212 plugin->send_configure_change();
00213 return 1;
00214 }
00215
00216
00217
00218
00219 ShiftInterlaceEven::ShiftInterlaceEven(ShiftInterlaceMain *plugin, int x, int y)
00220 : BC_ISlider(x,
00221 y,
00222 0,
00223 200,
00224 200,
00225 -100,
00226 100,
00227 plugin->config.even_offset)
00228 {
00229 this->plugin = plugin;
00230 }
00231
00232
00233 int ShiftInterlaceEven::handle_event()
00234 {
00235 plugin->config.even_offset = get_value();
00236 plugin->send_configure_change();
00237 return 1;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 PLUGIN_THREAD_OBJECT(ShiftInterlaceMain, ShiftInterlaceThread, ShiftInterlaceWindow)
00248
00249
00250
00251 ShiftInterlaceMain::ShiftInterlaceMain(PluginServer *server)
00252 : PluginVClient(server)
00253 {
00254 PLUGIN_CONSTRUCTOR_MACRO
00255 }
00256
00257 ShiftInterlaceMain::~ShiftInterlaceMain()
00258 {
00259 PLUGIN_DESTRUCTOR_MACRO
00260 }
00261
00262
00263 char* ShiftInterlaceMain::plugin_title() { return N_("ShiftInterlace"); }
00264 int ShiftInterlaceMain::is_realtime() { return 1; }
00265
00266
00267 SHOW_GUI_MACRO(ShiftInterlaceMain, ShiftInterlaceThread)
00268
00269 NEW_PICON_MACRO(ShiftInterlaceMain)
00270
00271 SET_STRING_MACRO(ShiftInterlaceMain)
00272
00273 LOAD_CONFIGURATION_MACRO(ShiftInterlaceMain, ShiftInterlaceConfig)
00274
00275 RAISE_WINDOW_MACRO(ShiftInterlaceMain)
00276
00277
00278 int ShiftInterlaceMain::load_defaults()
00279 {
00280 char directory[1024], string[1024];
00281
00282 sprintf(directory, "%sshiftinterlace.rc", BCASTDIR);
00283
00284
00285 defaults = new BC_Hash(directory);
00286 defaults->load();
00287
00288 config.odd_offset = defaults->get("ODD_OFFSET", config.odd_offset);
00289 config.even_offset = defaults->get("EVEN_OFFSET", config.even_offset);
00290 return 0;
00291 }
00292
00293 int ShiftInterlaceMain::save_defaults()
00294 {
00295 defaults->update("ODD_OFFSET", config.odd_offset);
00296 defaults->update("EVEN_OFFSET", config.even_offset);
00297 defaults->save();
00298 return 0;
00299 }
00300
00301 void ShiftInterlaceMain::save_data(KeyFrame *keyframe)
00302 {
00303 FileXML output;
00304
00305
00306 output.set_shared_string(keyframe->data, MESSAGESIZE);
00307 output.tag.set_title("SHIFTINTERLACE");
00308 output.tag.set_property("ODD_OFFSET", config.odd_offset);
00309 output.tag.set_property("EVEN_OFFSET", config.even_offset);
00310 output.append_tag();
00311 output.tag.set_title("/SHIFTINTERLACE");
00312 output.append_tag();
00313 output.append_newline();
00314 output.terminate_string();
00315
00316 }
00317
00318 void ShiftInterlaceMain::read_data(KeyFrame *keyframe)
00319 {
00320 FileXML input;
00321
00322 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00323
00324 int result = 0;
00325
00326 while(!result)
00327 {
00328 result = input.read_tag();
00329
00330 if(!result)
00331 {
00332 if(input.tag.title_is("SHIFTINTERLACE"))
00333 {
00334 config.odd_offset = input.tag.get_property("ODD_OFFSET", config.odd_offset);
00335 config.even_offset = input.tag.get_property("EVEN_OFFSET", config.even_offset);
00336 }
00337 }
00338 }
00339 }
00340
00341 void ShiftInterlaceMain::update_gui()
00342 {
00343 if(thread)
00344 {
00345 load_configuration();
00346 thread->window->lock_window();
00347 thread->window->odd_offset->update(config.odd_offset);
00348 thread->window->even_offset->update(config.even_offset);
00349 thread->window->unlock_window();
00350 }
00351 }
00352
00353
00354 #define SHIFT_ROW_MACRO(components, type, chroma_offset) \
00355 { \
00356 type *input_row = (type*)input_frame->get_rows()[row]; \
00357 type *output_row = (type*)output_frame->get_rows()[row]; \
00358 \
00359 if(offset < 0) \
00360 { \
00361 int i, j; \
00362 for(i = 0, j = -offset; \
00363 j < w; \
00364 i++, j++) \
00365 { \
00366 output_row[i * components + 0] = input_row[j * components + 0]; \
00367 output_row[i * components + 1] = input_row[j * components + 1]; \
00368 output_row[i * components + 2] = input_row[j * components + 2]; \
00369 if(components == 4) output_row[i * components + 3] = input_row[j * components + 3]; \
00370 } \
00371 \
00372 for( ; i < w; i++) \
00373 { \
00374 output_row[i * components + 0] = 0; \
00375 output_row[i * components + 1] = chroma_offset; \
00376 output_row[i * components + 2] = chroma_offset; \
00377 if(components == 4) output_row[i * components + 3] = 0; \
00378 } \
00379 } \
00380 else \
00381 { \
00382 int i, j; \
00383 for(i = w - offset - 1, j = w - 1; \
00384 j >= offset; \
00385 i--, \
00386 j--) \
00387 { \
00388 output_row[j * components + 0] = input_row[i * components + 0]; \
00389 output_row[j * components + 1] = input_row[i * components + 1]; \
00390 output_row[j * components + 2] = input_row[i * components + 2]; \
00391 if(components == 4) output_row[j * components + 3] = input_row[i * components + 3]; \
00392 } \
00393 \
00394 for( ; j >= 0; j--) \
00395 { \
00396 output_row[j * components + 0] = 0; \
00397 output_row[j * components + 1] = chroma_offset; \
00398 output_row[j * components + 2] = chroma_offset; \
00399 if(components == 4) output_row[j * components + 3] = 0; \
00400 } \
00401 } \
00402 }
00403
00404
00405 void ShiftInterlaceMain::shift_row(VFrame *input_frame,
00406 VFrame *output_frame,
00407 int offset,
00408 int row)
00409 {
00410 int w = input_frame->get_w();
00411 switch(input_frame->get_color_model())
00412 {
00413 case BC_RGB888:
00414 SHIFT_ROW_MACRO(3, unsigned char, 0x0)
00415 break;
00416 case BC_RGB_FLOAT:
00417 SHIFT_ROW_MACRO(3, float, 0x0)
00418 break;
00419 case BC_YUV888:
00420 SHIFT_ROW_MACRO(3, unsigned char, 0x80)
00421 break;
00422 case BC_RGBA_FLOAT:
00423 SHIFT_ROW_MACRO(4, float, 0x0)
00424 break;
00425 case BC_RGBA8888:
00426 SHIFT_ROW_MACRO(4, unsigned char, 0x0)
00427 break;
00428 case BC_YUVA8888:
00429 SHIFT_ROW_MACRO(4, unsigned char, 0x80)
00430 break;
00431 case BC_RGB161616:
00432 SHIFT_ROW_MACRO(3, uint16_t, 0x0)
00433 break;
00434 case BC_YUV161616:
00435 SHIFT_ROW_MACRO(3, uint16_t, 0x8000)
00436 break;
00437 case BC_RGBA16161616:
00438 SHIFT_ROW_MACRO(4, uint16_t, 0x0)
00439 break;
00440 case BC_YUVA16161616:
00441 SHIFT_ROW_MACRO(4, uint16_t, 0x8000)
00442 break;
00443 }
00444 }
00445
00446 int ShiftInterlaceMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00447 {
00448 load_configuration();
00449
00450 int h = input_ptr->get_h();
00451 for(int i = 0; i < h; i++)
00452 {
00453 if(i % 2)
00454 shift_row(input_ptr, output_ptr, config.even_offset, i);
00455 else
00456 shift_row(input_ptr, output_ptr, config.odd_offset, i);
00457 }
00458
00459 return 0;
00460 }
00461
00462