00001 #include <math.h>
00002 #include <stdint.h>
00003 #include <string.h>
00004
00005 #include "bcdisplayinfo.h"
00006 #include "clip.h"
00007 #include "bchash.h"
00008 #include "filexml.h"
00009 #include "timefront.h"
00010 #include "keyframe.h"
00011 #include "language.h"
00012 #include "overlayframe.h"
00013 #include "picon_png.h"
00014 #include "vframe.h"
00015
00016
00017
00018
00019 REGISTER_PLUGIN(TimeFrontMain)
00020
00021
00022
00023
00024
00025
00026 TimeFrontConfig::TimeFrontConfig()
00027 {
00028 angle = 0;
00029 in_radius = 0;
00030 out_radius = 100;
00031 frame_range = 16;
00032 track_usage = TimeFrontConfig::OTHERTRACK_INTENSITY;
00033 shape = TimeFrontConfig::LINEAR;
00034 rate = TimeFrontConfig::LINEAR;
00035 center_x = 50;
00036 center_y = 50;
00037 invert = 0;
00038 show_grayscale = 0;
00039 }
00040
00041 int TimeFrontConfig::equivalent(TimeFrontConfig &that)
00042 {
00043 return (EQUIV(angle, that.angle) &&
00044 EQUIV(in_radius, that.in_radius) &&
00045 EQUIV(out_radius, that.out_radius) &&
00046 frame_range == that.frame_range &&
00047 track_usage == that.track_usage &&
00048 shape == that.shape &&
00049 rate == that.rate &&
00050 EQUIV(center_x, that.center_x) &&
00051 EQUIV(center_y, that.center_y) &&
00052 invert == that.invert &&
00053 show_grayscale == that.show_grayscale);
00054 }
00055
00056 void TimeFrontConfig::copy_from(TimeFrontConfig &that)
00057 {
00058 angle = that.angle;
00059 in_radius = that.in_radius;
00060 out_radius = that.out_radius;
00061 frame_range = that.frame_range;
00062 track_usage = that.track_usage;
00063 shape = that.shape;
00064 rate = that.rate;
00065 center_x = that.center_x;
00066 center_y = that.center_y;
00067 invert = that.invert;
00068 show_grayscale = that.show_grayscale;
00069 }
00070
00071 void TimeFrontConfig::interpolate(TimeFrontConfig &prev,
00072 TimeFrontConfig &next,
00073 long prev_frame,
00074 long next_frame,
00075 long current_frame)
00076 {
00077 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00078 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00079
00080
00081 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
00082 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
00083 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
00084 frame_range = (int)(prev.frame_range * prev_scale + next.frame_range * next_scale);
00085 track_usage = prev.track_usage;
00086 shape = prev.shape;
00087 rate = prev.rate;
00088 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
00089 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
00090 invert = prev.invert;
00091 show_grayscale = prev.show_grayscale;
00092 }
00093
00094
00095
00096
00097
00098
00099 PLUGIN_THREAD_OBJECT(TimeFrontMain, TimeFrontThread, TimeFrontWindow)
00100
00101
00102 TimeFrontWindow::TimeFrontWindow(TimeFrontMain *plugin, int x, int y)
00103 : BC_Window(plugin->gui_string,
00104 x,
00105 y,
00106 350,
00107 290,
00108 350,
00109 290,
00110 0,
00111 1)
00112 {
00113 this->plugin = plugin;
00114 angle = 0;
00115 angle_title = 0;
00116 center_x = 0;
00117 center_y = 0;
00118 center_x_title = 0;
00119 center_y_title = 0;
00120 rate_title = 0;
00121 rate = 0;
00122 in_radius_title = 0;
00123 in_radius = 0;
00124 out_radius_title = 0;
00125 out_radius = 0;
00126 track_usage_title = 0;
00127 track_usage = 0;
00128
00129 }
00130
00131 TimeFrontWindow::~TimeFrontWindow()
00132 {
00133 }
00134
00135 int TimeFrontWindow::create_objects()
00136 {
00137 int x = 10, y = 10;
00138 BC_Title *title;
00139
00140 add_subwindow(title = new BC_Title(x, y, _("Type:")));
00141 add_subwindow(shape = new TimeFrontShape(plugin,
00142 this,
00143 x + title->get_w() + 10,
00144 y));
00145 shape->create_objects();
00146 y += 40;
00147 shape_x = x;
00148 shape_y = y;
00149 y += 140;
00150 add_subwindow(title = new BC_Title(x, y, _("Time range:")));
00151 add_subwindow(frame_range = new TimeFrontFrameRange(plugin, x + title->get_w() + 10, y));
00152 frame_range_x = x + frame_range->get_w() + 10;
00153 frame_range_y = y;
00154 y += 35;
00155 update_shape();
00156
00157 add_subwindow(invert = new TimeFrontInvert(plugin, x, y));
00158 add_subwindow(show_grayscale = new TimeFrontShowGrayscale(plugin, x+ 100, y));
00159
00160
00161 show_window();
00162 flush();
00163 return 0;
00164 }
00165
00166 void TimeFrontWindow::update_shape()
00167 {
00168 int x = shape_x, y = shape_y;
00169
00170 if(plugin->config.shape == TimeFrontConfig::LINEAR)
00171 {
00172 delete center_x_title;
00173 delete center_y_title;
00174 delete center_x;
00175 delete center_y;
00176 delete track_usage_title;
00177 delete track_usage;
00178 center_x_title = 0;
00179 center_y_title = 0;
00180 center_x = 0;
00181 center_y = 0;
00182 track_usage_title = 0;
00183 track_usage = 0;
00184 if(!angle)
00185 {
00186 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
00187 add_subwindow(angle = new TimeFrontAngle(plugin, x + angle_title->get_w() + 10, y));
00188 }
00189 if(!rate){
00190 y = shape_y + 40;
00191
00192 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
00193 add_subwindow(rate = new TimeFrontRate(plugin,
00194 x + rate_title->get_w() + 10,
00195 y));
00196 rate->create_objects();
00197 y += 40;
00198 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
00199 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
00200 y += 30;
00201 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
00202 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
00203 y += 35;
00204
00205 }
00206 } else
00207 if(plugin->config.shape == TimeFrontConfig::RADIAL)
00208 {
00209 delete angle_title;
00210 delete angle;
00211 delete track_usage_title;
00212 delete track_usage;
00213 angle_title = 0;
00214 angle = 0;
00215 track_usage_title = 0;
00216 track_usage = 0;
00217 if(!center_x)
00218 {
00219 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
00220 add_subwindow(center_x = new TimeFrontCenterX(plugin,
00221 x + center_x_title->get_w() + 10,
00222 y));
00223 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
00224 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
00225 add_subwindow(center_y = new TimeFrontCenterY(plugin,
00226 x + center_y_title->get_w() + 10,
00227 y));
00228 }
00229
00230
00231 if(!rate)
00232 {
00233 y = shape_y + 40;
00234 x = shape_x;
00235 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
00236 add_subwindow(rate = new TimeFrontRate(plugin,
00237 x + rate_title->get_w() + 10,
00238 y));
00239 rate->create_objects();
00240 y += 40;
00241 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
00242 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
00243 y += 30;
00244 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
00245 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
00246 y += 35;
00247 }
00248 } else
00249 if(plugin->config.shape == TimeFrontConfig::OTHERTRACK)
00250 {
00251 delete center_x_title;
00252 delete center_y_title;
00253 delete center_x;
00254 delete center_y;
00255 delete angle_title;
00256 delete angle;
00257 delete rate_title;
00258 delete rate;
00259 delete in_radius_title;
00260 delete in_radius;
00261 delete out_radius_title;
00262 delete out_radius;
00263 center_x_title = 0;
00264 center_y_title = 0;
00265 center_x = 0;
00266 center_y = 0;
00267 angle_title = 0;
00268 angle = 0;
00269 rate_title = 0;
00270 rate = 0;
00271 in_radius_title = 0;
00272 in_radius = 0;
00273 out_radius_title = 0;
00274 out_radius = 0;
00275 if(!track_usage)
00276 {
00277 add_subwindow(track_usage_title = new BC_Title(x, y, _("As timefront use:")));
00278 add_subwindow(track_usage = new TimeFrontTrackUsage(plugin,
00279 this,
00280 x + track_usage_title->get_w() + 10,
00281 y));
00282 track_usage->create_objects();
00283
00284 }
00285 } else
00286 if(plugin->config.shape == TimeFrontConfig::ALPHA)
00287 {
00288 delete center_x_title;
00289 delete center_y_title;
00290 delete center_x;
00291 delete center_y;
00292 delete angle_title;
00293 delete angle;
00294 delete rate_title;
00295 delete rate;
00296 delete in_radius_title;
00297 delete in_radius;
00298 delete out_radius_title;
00299 delete out_radius;
00300 delete track_usage_title;
00301 delete track_usage;
00302 center_x_title = 0;
00303 center_y_title = 0;
00304 center_x = 0;
00305 center_y = 0;
00306 angle_title = 0;
00307 angle = 0;
00308 rate_title = 0;
00309 rate = 0;
00310 in_radius_title = 0;
00311 in_radius = 0;
00312 out_radius_title = 0;
00313 out_radius = 0;
00314 track_usage_title = 0;
00315 track_usage = 0;
00316
00317 }
00318
00319 }
00320
00321 int TimeFrontWindow::close_event()
00322 {
00323
00324 set_done(1);
00325 return 1;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 TimeFrontShape::TimeFrontShape(TimeFrontMain *plugin,
00339 TimeFrontWindow *gui,
00340 int x,
00341 int y)
00342 : BC_PopupMenu(x, y, 190, to_text(plugin->config.shape), 1)
00343 {
00344 this->plugin = plugin;
00345 this->gui = gui;
00346 }
00347 void TimeFrontShape::create_objects()
00348 {
00349 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
00350 add_item(new BC_MenuItem(to_text(TimeFrontConfig::RADIAL)));
00351 add_item(new BC_MenuItem(to_text(TimeFrontConfig::ALPHA)));
00352 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK)));
00353 }
00354 char* TimeFrontShape::to_text(int shape)
00355 {
00356 switch(shape)
00357 {
00358 case TimeFrontConfig::LINEAR:
00359 return _("Linear");
00360 case TimeFrontConfig::OTHERTRACK:
00361 return _("Other track as timefront");
00362 case TimeFrontConfig::ALPHA:
00363 return _("Alpha as timefront");
00364 default:
00365 return _("Radial");
00366 }
00367 }
00368 int TimeFrontShape::from_text(char *text)
00369 {
00370 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
00371 return TimeFrontConfig::LINEAR;
00372 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK)))
00373 return TimeFrontConfig::OTHERTRACK;
00374 if(!strcmp(text, to_text(TimeFrontConfig::ALPHA)))
00375 return TimeFrontConfig::ALPHA;
00376 return TimeFrontConfig::RADIAL;
00377 }
00378 int TimeFrontShape::handle_event()
00379 {
00380 plugin->config.shape = from_text(get_text());
00381 gui->update_shape();
00382 plugin->send_configure_change();
00383 }
00384
00385
00386 TimeFrontTrackUsage::TimeFrontTrackUsage(TimeFrontMain *plugin,
00387 TimeFrontWindow *gui,
00388 int x,
00389 int y)
00390 : BC_PopupMenu(x, y, 140, to_text(plugin->config.track_usage), 1)
00391 {
00392 this->plugin = plugin;
00393 this->gui = gui;
00394 }
00395 void TimeFrontTrackUsage::create_objects()
00396 {
00397 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)));
00398 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_ALPHA)));
00399 }
00400 char* TimeFrontTrackUsage::to_text(int track_usage)
00401 {
00402 switch(track_usage)
00403 {
00404 case TimeFrontConfig::OTHERTRACK_INTENSITY:
00405 return _("Intensity");
00406 case TimeFrontConfig::OTHERTRACK_ALPHA:
00407 return _("Alpha mask");
00408 default:
00409 return _("Unknown");
00410 }
00411 }
00412 int TimeFrontTrackUsage::from_text(char *text)
00413 {
00414 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)))
00415 return TimeFrontConfig::OTHERTRACK_INTENSITY;
00416 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_ALPHA)))
00417 return TimeFrontConfig::OTHERTRACK_ALPHA;
00418
00419 return TimeFrontConfig::OTHERTRACK_INTENSITY;
00420 }
00421 int TimeFrontTrackUsage::handle_event()
00422 {
00423 plugin->config.track_usage = from_text(get_text());
00424 gui->update_shape();
00425 plugin->send_configure_change();
00426 }
00427
00428
00429
00430
00431 TimeFrontCenterX::TimeFrontCenterX(TimeFrontMain *plugin, int x, int y)
00432 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
00433 {
00434 this->plugin = plugin;
00435 }
00436 int TimeFrontCenterX::handle_event()
00437 {
00438 plugin->config.center_x = get_value();
00439 plugin->send_configure_change();
00440 return 1;
00441 }
00442
00443
00444
00445 TimeFrontCenterY::TimeFrontCenterY(TimeFrontMain *plugin, int x, int y)
00446 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
00447 {
00448 this->plugin = plugin;
00449 }
00450
00451 int TimeFrontCenterY::handle_event()
00452 {
00453 plugin->config.center_y = get_value();
00454 plugin->send_configure_change();
00455 return 1;
00456 }
00457
00458
00459
00460
00461 TimeFrontAngle::TimeFrontAngle(TimeFrontMain *plugin, int x, int y)
00462 : BC_FPot(x,
00463 y,
00464 plugin->config.angle,
00465 -180,
00466 180)
00467 {
00468 this->plugin = plugin;
00469 }
00470
00471 int TimeFrontAngle::handle_event()
00472 {
00473 plugin->config.angle = get_value();
00474 plugin->send_configure_change();
00475 return 1;
00476 }
00477
00478
00479 TimeFrontRate::TimeFrontRate(TimeFrontMain *plugin, int x, int y)
00480 : BC_PopupMenu(x,
00481 y,
00482 100,
00483 to_text(plugin->config.rate),
00484 1)
00485 {
00486 this->plugin = plugin;
00487 }
00488 void TimeFrontRate::create_objects()
00489 {
00490 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
00491 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LOG)));
00492 add_item(new BC_MenuItem(to_text(TimeFrontConfig::SQUARE)));
00493 }
00494 char* TimeFrontRate::to_text(int shape)
00495 {
00496 switch(shape)
00497 {
00498 case TimeFrontConfig::LINEAR:
00499 return _("Linear");
00500 case TimeFrontConfig::LOG:
00501 return _("Log");
00502 default:
00503 return _("Square");
00504 }
00505 }
00506 int TimeFrontRate::from_text(char *text)
00507 {
00508 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
00509 return TimeFrontConfig::LINEAR;
00510 if(!strcmp(text, to_text(TimeFrontConfig::LOG)))
00511 return TimeFrontConfig::LOG;
00512 return TimeFrontConfig::SQUARE;
00513 }
00514 int TimeFrontRate::handle_event()
00515 {
00516 plugin->config.rate = from_text(get_text());
00517 plugin->send_configure_change();
00518 return 1;
00519 }
00520
00521
00522
00523 TimeFrontInRadius::TimeFrontInRadius(TimeFrontMain *plugin, int x, int y)
00524 : BC_FSlider(x,
00525 y,
00526 0,
00527 200,
00528 200,
00529 (float)0,
00530 (float)100,
00531 (float)plugin->config.in_radius)
00532 {
00533 this->plugin = plugin;
00534 }
00535
00536 int TimeFrontInRadius::handle_event()
00537 {
00538 plugin->config.in_radius = get_value();
00539 plugin->send_configure_change();
00540 return 1;
00541 }
00542
00543
00544 TimeFrontOutRadius::TimeFrontOutRadius(TimeFrontMain *plugin, int x, int y)
00545 : BC_FSlider(x,
00546 y,
00547 0,
00548 200,
00549 200,
00550 (float)0,
00551 (float)100,
00552 (float)plugin->config.out_radius)
00553 {
00554 this->plugin = plugin;
00555 }
00556
00557 int TimeFrontOutRadius::handle_event()
00558 {
00559 plugin->config.out_radius = get_value();
00560 plugin->send_configure_change();
00561 return 1;
00562 }
00563
00564 TimeFrontFrameRange::TimeFrontFrameRange(TimeFrontMain *plugin, int x, int y)
00565 : BC_ISlider(x,
00566 y,
00567 0,
00568 200,
00569 200,
00570 (int)1,
00571 (int)255,
00572 (int)plugin->config.frame_range)
00573 {
00574 this->plugin = plugin;
00575 }
00576
00577 int TimeFrontFrameRange::handle_event()
00578 {
00579 plugin->config.frame_range = get_value();
00580 plugin->send_configure_change();
00581 return 1;
00582 }
00583
00584
00585 TimeFrontInvert::TimeFrontInvert(TimeFrontMain *client, int x, int y)
00586 : BC_CheckBox(x,
00587 y,
00588 client->config.invert,
00589 _("Inversion"))
00590 {
00591 this->plugin = client;
00592 }
00593
00594 int TimeFrontInvert::handle_event()
00595 {
00596 plugin->config.invert = get_value();
00597 plugin->send_configure_change();
00598 return 1;
00599 }
00600
00601 TimeFrontShowGrayscale::TimeFrontShowGrayscale(TimeFrontMain *client, int x, int y)
00602 : BC_CheckBox(x,
00603 y,
00604 client->config.show_grayscale,
00605 _("Show grayscale (for tuning"))
00606 {
00607 this->plugin = client;
00608 }
00609
00610 int TimeFrontShowGrayscale::handle_event()
00611 {
00612 plugin->config.show_grayscale = get_value();
00613 plugin->send_configure_change();
00614 return 1;
00615 }
00616
00617
00618
00619 TimeFrontMain::TimeFrontMain(PluginServer *server)
00620 : PluginVClient(server)
00621 {
00622 PLUGIN_CONSTRUCTOR_MACRO
00623 need_reconfigure = 1;
00624 gradient = 0;
00625 engine = 0;
00626 overlayer = 0;
00627 }
00628
00629 TimeFrontMain::~TimeFrontMain()
00630 {
00631 PLUGIN_DESTRUCTOR_MACRO
00632
00633 if(gradient) delete gradient;
00634 if(engine) delete engine;
00635 if(overlayer) delete overlayer;
00636 }
00637
00638 char* TimeFrontMain::plugin_title() { return N_("TimeFront"); }
00639 int TimeFrontMain::is_realtime() { return 1; }
00640 int TimeFrontMain::is_multichannel() { return 1; }
00641
00642
00643 NEW_PICON_MACRO(TimeFrontMain)
00644
00645 SHOW_GUI_MACRO(TimeFrontMain, TimeFrontThread)
00646
00647 SET_STRING_MACRO(TimeFrontMain)
00648
00649 RAISE_WINDOW_MACRO(TimeFrontMain)
00650
00651 LOAD_CONFIGURATION_MACRO(TimeFrontMain, TimeFrontConfig)
00652
00653 int TimeFrontMain::is_synthesis()
00654 {
00655 return 1;
00656 }
00657
00658 #define GRADIENTFROMAVG(type, inttype, components, maxval) \
00659 for(int i = 0; i < tfframe->get_h(); i++) \
00660 { \
00661 type *in_row = (type *)tfframe->get_rows()[i]; \
00662 unsigned char *grad_row = gradient->get_rows()[i]; \
00663 for(int j = 0; j < tfframe->get_w(); j++) \
00664 { \
00665 inttype tmp = (inttype) in_row[j * components] + \
00666 in_row[j * components + 1] + \
00667 in_row[j * components + 2]; \
00668 if (components == 3) \
00669 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp / maxval / 3, 0.0F, config.frame_range)); \
00670 else if(components == 4) \
00671 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp * in_row[j * components + 3] / maxval / maxval / 3, 0.0F, config.frame_range)); \
00672 } \
00673 }
00674
00675 #define GRADIENTFROMCHANNEL(type, components, max, channel) \
00676 for(int i = 0; i < tfframe->get_h(); i++) \
00677 { \
00678 type *in_row = (type *)tfframe->get_rows()[i]; \
00679 unsigned char *grad_row = gradient->get_rows()[i]; \
00680 for(int j = 0; j < tfframe->get_w(); j++) \
00681 { \
00682 if (components == 3) \
00683 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] / max, 0.0F, config.frame_range)); \
00684 else if(components == 4) \
00685 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] * in_row[j * components + 3]/ max /max, 0.0F, config.frame_range)); \
00686 } \
00687 }
00688
00689 #define SETALPHA(type, max) \
00690 for(int i = 0; i < outframes[0]->get_h(); i++) \
00691 { \
00692 type *out_row = (type *)outframes[0]->get_rows()[i]; \
00693 for(int j = 0; j < outframes[0]->get_w(); j++) \
00694 { \
00695 out_row[j * 4 + 3] = max; \
00696 } \
00697 }
00698
00699 #define GRADIENTTOPICTURE(type, inttype, components, max, invertion) \
00700 for(int i = 0; i < height; i++) \
00701 { \
00702 type *out_row = (type *)outframes[0]->get_rows()[i]; \
00703 unsigned char *grad_row = gradient->get_rows()[i]; \
00704 for (int j = 0; j < width; j++) \
00705 { \
00706 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
00707 out_row[1] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
00708 out_row[2] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
00709 if (components == 4) \
00710 out_row[3] = max; \
00711 out_row += components; \
00712 grad_row ++; \
00713 } \
00714 }
00715
00716 #define GRADIENTTOYUVPICTURE(type, inttype, components, max, invertion) \
00717 for(int i = 0; i < height; i++) \
00718 { \
00719 type *out_row = (type *)outframes[0]->get_rows()[i]; \
00720 unsigned char *grad_row = gradient->get_rows()[i]; \
00721 for (int j = 0; j < width; j++) \
00722 { \
00723 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
00724 out_row[1] = max/2; \
00725 out_row[2] = max/2; \
00726 if (components == 4) \
00727 out_row[3] = max; \
00728 out_row += components; \
00729 grad_row ++; \
00730 } \
00731 }
00732
00733 #define COMPOSITEIMAGE(type, components, invertion) \
00734 for (int i = 0; i < height; i++) \
00735 { \
00736 type *out_row = (type *)outframes[0]->get_rows()[i]; \
00737 unsigned char *gradient_row = gradient->get_rows()[i]; \
00738 for (int j = 0; j < width; j++) \
00739 { \
00740 unsigned int choice = invertion gradient_row[j]; \
00741 { \
00742 out_row[0] = framelist[choice]->get_rows()[i][j * components + 0]; \
00743 out_row[1] = framelist[choice]->get_rows()[i][j * components + 1]; \
00744 out_row[2] = framelist[choice]->get_rows()[i][j * components + 2]; \
00745 if (components == 4) \
00746 out_row[3] = framelist[choice]->get_rows()[i][j * components + 3]; \
00747 } \
00748 out_row += components; \
00749 } \
00750 }
00751
00752
00753
00754 int TimeFrontMain::process_buffer(VFrame **frame,
00755 int64_t start_position,
00756 double frame_rate)
00757
00758 {
00759 VFrame **outframes = frame;
00760 VFrame *(framelist[1024]);
00761 framelist[0] = new VFrame (0, outframes[0]->get_w(), outframes[0]->get_h(), outframes[0]->get_color_model());
00762 read_frame(framelist[0],
00763 0,
00764 start_position,
00765 frame_rate);
00766 this->input = framelist[0];
00767 this->output = outframes[0];
00768 need_reconfigure |= load_configuration();
00769 if (config.shape == TimeFrontConfig::OTHERTRACK)
00770 {
00771
00772 if (get_total_buffers() != 2)
00773 {
00774
00775 printf("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n");
00776 return 0;
00777 }
00778 if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h())
00779 {
00780 printf("Sizes of master track and timefront track do not match\n");
00781 return 0;
00782 }
00783 }
00784
00785
00786 if(need_reconfigure)
00787 {
00788 need_reconfigure = 0;
00789
00790 if(!gradient) gradient = new VFrame(0,
00791 outframes[0]->get_w(),
00792 outframes[0]->get_h(),
00793 BC_A8);
00794
00795
00796 if (config.shape != TimeFrontConfig::OTHERTRACK &&
00797 config.shape != TimeFrontConfig::ALPHA)
00798 {
00799 if(!engine) engine = new TimeFrontServer(this,
00800 get_project_smp() + 1,
00801 get_project_smp() + 1);
00802 engine->process_packages();
00803 }
00804
00805 }
00806 if (config.shape == TimeFrontConfig::ALPHA)
00807 {
00808 if(!gradient) gradient = new VFrame(0,
00809 outframes[0]->get_w(),
00810 outframes[0]->get_h(),
00811 BC_A8);
00812 VFrame *tfframe = framelist[0];
00813 switch (tfframe->get_color_model())
00814 {
00815 case BC_YUVA8888:
00816 case BC_RGBA8888:
00817 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
00818
00819
00820 break;
00821 case BC_RGBA_FLOAT:
00822 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
00823 break;
00824
00825 default:
00826 {
00827 printf("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n");
00828 return 1;
00829 break;
00830 }
00831 }
00832
00833 } else
00834 if (config.shape == TimeFrontConfig::OTHERTRACK)
00835 {
00836 if(!gradient) gradient = new VFrame(0,
00837 outframes[0]->get_w(),
00838 outframes[0]->get_h(),
00839 BC_A8);
00840 VFrame *tfframe = outframes[1];
00841 read_frame(tfframe,
00842 1,
00843 start_position,
00844 frame_rate);
00845 if (config.track_usage == TimeFrontConfig::OTHERTRACK_INTENSITY)
00846 {
00847 switch (tfframe->get_color_model())
00848 {
00849 case BC_RGBA8888:
00850 GRADIENTFROMAVG(unsigned char, unsigned short, 4, 255);
00851 break;
00852 case BC_RGB888:
00853 GRADIENTFROMAVG(unsigned char, unsigned short, 3, 255);
00854 break;
00855 case BC_RGB_FLOAT:
00856 GRADIENTFROMAVG(float, float, 3, 1.0f);
00857 break;
00858 case BC_RGBA_FLOAT:
00859 GRADIENTFROMAVG(float, float, 4, 1.0f);
00860 break;
00861 case BC_YUV888:
00862 GRADIENTFROMCHANNEL(unsigned char, 3, 255, 0);
00863 break;
00864 case BC_YUVA8888:
00865 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 0);
00866 break;
00867 default:
00868 break;
00869 }
00870 } else
00871 if (config.track_usage == TimeFrontConfig::OTHERTRACK_ALPHA)
00872 {
00873 switch (tfframe->get_color_model())
00874 {
00875 case BC_YUVA8888:
00876 case BC_RGBA8888:
00877 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
00878
00879
00880 break;
00881 case BC_RGBA_FLOAT:
00882 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
00883 break;
00884
00885 default:
00886 {
00887 printf("TimeFront plugin error: ALPHA track used, but project color model does not have alpha\n");
00888 return 1;
00889 break;
00890 }
00891 }
00892 } else
00893 {
00894 printf("TimeFront plugin error: unsupported track_usage parameter\n");
00895 return 1;
00896 }
00897 }
00898
00899 if (!config.show_grayscale)
00900 {
00901 for (int i = 1; i <= config.frame_range; i++)
00902 {
00903 framelist[i] = new VFrame (0, outframes[0]->get_w(), outframes[0]->get_h(), outframes[0]->get_color_model());
00904
00905 read_frame(framelist[i],
00906 0,
00907 start_position - i,
00908 frame_rate);
00909 }
00910 }
00911
00912
00913 int width = outframes[0]->get_w();
00914 int height = outframes[0]->get_h();
00915 if (config.show_grayscale)
00916 {
00917 if (!config.invert)
00918 {
00919 switch (outframes[0]->get_color_model())
00920 {
00921 case BC_RGB888:
00922 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, );
00923 break;
00924 case BC_RGBA8888:
00925 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, );
00926 break;
00927 case BC_YUV888:
00928 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, );
00929 break;
00930 case BC_YUVA8888:
00931 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, );
00932 break;
00933 case BC_RGB_FLOAT:
00934 GRADIENTTOPICTURE(float, float, 3, 1.0f, );
00935 break;
00936 case BC_RGBA_FLOAT:
00937 GRADIENTTOPICTURE(float, float, 4, 1.0f, );
00938 break;
00939 default:
00940 break;
00941 }
00942 } else
00943 {
00944 switch (outframes[0]->get_color_model())
00945 {
00946 case BC_RGB888:
00947 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
00948 break;
00949 case BC_RGBA8888:
00950 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
00951 break;
00952 case BC_YUV888:
00953 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
00954 break;
00955 case BC_YUVA8888:
00956 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
00957 break;
00958 case BC_RGB_FLOAT:
00959 GRADIENTTOPICTURE(float, float, 3, 1.0f, config.frame_range -);
00960 break;
00961 case BC_RGBA_FLOAT:
00962 GRADIENTTOPICTURE(float, float, 4, 1.0f, config.frame_range -);
00963 break;
00964 default:
00965 break;
00966 }
00967 }
00968 } else
00969 if (!config.invert)
00970 {
00971 switch (outframes[0]->get_color_model())
00972 {
00973 case BC_RGB888:
00974 COMPOSITEIMAGE(unsigned char, 3, );
00975 break;
00976 case BC_RGBA8888:
00977 COMPOSITEIMAGE(unsigned char, 4, );
00978 break;
00979 case BC_YUV888:
00980 COMPOSITEIMAGE(unsigned char, 3, );
00981 break;
00982 case BC_YUVA8888:
00983 COMPOSITEIMAGE(unsigned char, 4, );
00984 break;
00985 case BC_RGB_FLOAT:
00986 COMPOSITEIMAGE(float, 3, );
00987 break;
00988 case BC_RGBA_FLOAT:
00989 COMPOSITEIMAGE(float, 4, );
00990 break;
00991
00992 default:
00993 break;
00994 }
00995 } else
00996 {
00997 switch (outframes[0]->get_color_model())
00998 {
00999 case BC_RGB888:
01000 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
01001 break;
01002 case BC_RGBA8888:
01003 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
01004 break;
01005 case BC_YUV888:
01006 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
01007 break;
01008 case BC_YUVA8888:
01009 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
01010 break;
01011 case BC_RGB_FLOAT:
01012 COMPOSITEIMAGE(float, 3, config.frame_range -);
01013 break;
01014 case BC_RGBA_FLOAT:
01015 COMPOSITEIMAGE(float, 4, config.frame_range -);
01016 break;
01017
01018 default:
01019 break;
01020 }
01021 }
01022 if (config.shape == TimeFrontConfig::ALPHA)
01023 {
01024
01025 switch (outframes[0]->get_color_model())
01026 {
01027 case BC_YUVA8888:
01028 case BC_RGBA8888:
01029 SETALPHA(unsigned char, 255);
01030 break;
01031 case BC_RGBA_FLOAT:
01032 SETALPHA(float, 1.0f);
01033 break;
01034
01035 default:
01036 break;
01037 }
01038 }
01039
01040 delete framelist[0];
01041 if (!config.show_grayscale)
01042 {
01043 for (int i = 1; i <= config.frame_range; i++)
01044 delete framelist[i];
01045 }
01046 return 0;
01047 }
01048
01049
01050 void TimeFrontMain::update_gui()
01051 {
01052 if(thread)
01053 {
01054 if(load_configuration())
01055 {
01056 thread->window->lock_window("TimeFrontMain::update_gui");
01057 thread->window->frame_range->update(config.frame_range);
01058 thread->window->shape->set_text(TimeFrontShape::to_text(config.shape));
01059 thread->window->show_grayscale->update(config.show_grayscale);
01060 thread->window->invert->update(config.invert);
01061 thread->window->shape->set_text(TimeFrontShape::to_text(config.shape));
01062 if (thread->window->rate)
01063 thread->window->rate->set_text(TimeFrontRate::to_text(config.rate));
01064 if (thread->window->in_radius)
01065 thread->window->in_radius->update(config.in_radius);
01066 if (thread->window->out_radius)
01067 thread->window->out_radius->update(config.out_radius);
01068 if (thread->window->track_usage)
01069 thread->window->track_usage->set_text(TimeFrontTrackUsage::to_text(config.track_usage));
01070 if(thread->window->angle)
01071 thread->window->angle->update(config.angle);
01072 if(thread->window->center_x)
01073 thread->window->center_x->update(config.center_x);
01074 if(thread->window->center_y)
01075 thread->window->center_y->update(config.center_y);
01076
01077 thread->window->update_shape();
01078 thread->window->unlock_window();
01079 }
01080 }
01081 }
01082
01083
01084 int TimeFrontMain::load_defaults()
01085 {
01086 char directory[1024], string[1024];
01087
01088 sprintf(directory, "%stimefront.rc", BCASTDIR);
01089
01090
01091 defaults = new BC_Hash(directory);
01092 defaults->load();
01093
01094
01095
01096
01097
01098
01099 config.angle = defaults->get("ANGLE", config.angle);
01100 config.in_radius = defaults->get("IN_RADIUS", config.in_radius);
01101 config.out_radius = defaults->get("OUT_RADIUS", config.out_radius);
01102 config.frame_range = defaults->get("FRAME_RANGE", config.frame_range);
01103 config.shape = defaults->get("SHAPE", config.shape);
01104 config.shape = defaults->get("TRACK_USAGE", config.track_usage);
01105 config.rate = defaults->get("RATE", config.rate);
01106 config.center_x = defaults->get("CENTER_X", config.center_x);
01107 config.center_y = defaults->get("CENTER_Y", config.center_y);
01108 config.invert = defaults->get("INVERT", config.invert);
01109 config.show_grayscale = defaults->get("SHOW_GRAYSCALE", config.show_grayscale);
01110 return 0;
01111 }
01112
01113
01114 int TimeFrontMain::save_defaults()
01115 {
01116 defaults->update("ANGLE", config.angle);
01117 defaults->update("IN_RADIUS", config.in_radius);
01118 defaults->update("OUT_RADIUS", config.out_radius);
01119 defaults->update("FRAME_RANGE", config.frame_range);
01120 defaults->update("RATE", config.rate);
01121 defaults->update("SHAPE", config.shape);
01122 defaults->update("TRACK_USAGE", config.track_usage);
01123 defaults->update("CENTER_X", config.center_x);
01124 defaults->update("CENTER_Y", config.center_y);
01125 defaults->update("INVERT", config.invert);
01126 defaults->update("SHOW_GRAYSCALE", config.show_grayscale);
01127 defaults->save();
01128 return 0;
01129 }
01130
01131
01132
01133 void TimeFrontMain::save_data(KeyFrame *keyframe)
01134 {
01135 FileXML output;
01136
01137
01138 output.set_shared_string(keyframe->data, MESSAGESIZE);
01139 output.tag.set_title("TIMEFRONT");
01140
01141 output.tag.set_property("ANGLE", config.angle);
01142 output.tag.set_property("IN_RADIUS", config.in_radius);
01143 output.tag.set_property("OUT_RADIUS", config.out_radius);
01144 output.tag.set_property("FRAME_RANGE", config.frame_range);
01145 output.tag.set_property("SHAPE", config.shape);
01146 output.tag.set_property("TRACK_USAGE", config.track_usage);
01147 output.tag.set_property("RATE", config.rate);
01148 output.tag.set_property("CENTER_X", config.center_x);
01149 output.tag.set_property("CENTER_Y", config.center_y);
01150 output.tag.set_property("INVERT", config.invert);
01151 output.tag.set_property("SHOW_GRAYSCALE", config.show_grayscale);
01152 output.append_tag();
01153 output.tag.set_title("/TIMEFRONT");
01154 output.append_tag();
01155 output.terminate_string();
01156 }
01157
01158 void TimeFrontMain::read_data(KeyFrame *keyframe)
01159 {
01160 FileXML input;
01161
01162 input.set_shared_string(keyframe->data, strlen(keyframe->data));
01163
01164 int result = 0;
01165
01166 while(!result)
01167 {
01168 result = input.read_tag();
01169
01170 if(!result)
01171 {
01172 if(input.tag.title_is("TIMEFRONT"))
01173 {
01174 config.angle = input.tag.get_property("ANGLE", config.angle);
01175 config.rate = input.tag.get_property("RATE", config.rate);
01176 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
01177 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
01178 config.frame_range = input.tag.get_property("FRAME_RANGE", config.frame_range);
01179 config.shape = input.tag.get_property("SHAPE", config.shape);
01180 config.track_usage = input.tag.get_property("TRACK_USAGE", config.track_usage);
01181 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
01182 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
01183 config.invert = input.tag.get_property("INVERT", config.invert);
01184 config.show_grayscale = input.tag.get_property("SHOW_GRAYSCALE", config.show_grayscale);
01185 }
01186 }
01187 }
01188 }
01189
01190
01191
01192
01193
01194
01195 TimeFrontPackage::TimeFrontPackage()
01196 : LoadPackage()
01197 {
01198 }
01199
01200
01201
01202
01203 TimeFrontUnit::TimeFrontUnit(TimeFrontServer *server, TimeFrontMain *plugin)
01204 : LoadClient(server)
01205 {
01206 this->plugin = plugin;
01207 this->server = server;
01208 }
01209
01210
01211 #define SQR(x) ((x) * (x))
01212 #define LOG_RANGE 1
01213
01214 #define CREATE_GRADIENT \
01215 { \
01216 \
01217 \
01218 a_table = (unsigned char *)malloc(sizeof(unsigned char) * gradient_size); \
01219 \
01220 for(int i = 0; i < gradient_size; i++) \
01221 { \
01222 float opacity; \
01223 float transparency; \
01224 switch(plugin->config.rate) \
01225 { \
01226 case TimeFrontConfig::LINEAR: \
01227 if(i < in_radius) \
01228 opacity = 0.0; \
01229 else \
01230 if(i >= out_radius) \
01231 opacity = 1.0; \
01232 else \
01233 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
01234 break; \
01235 case TimeFrontConfig::LOG: \
01236 opacity = 1 - exp(LOG_RANGE * -(float)(i - in_radius) / (out_radius - in_radius)); \
01237 break; \
01238 case TimeFrontConfig::SQUARE: \
01239 opacity = SQR((float)(i - in_radius) / (out_radius - in_radius)); \
01240 break; \
01241 } \
01242 \
01243 CLAMP(opacity, 0, 1); \
01244 transparency = 1.0 - opacity; \
01245 a_table[i] = (unsigned char)(out4 * opacity + in4 * transparency); \
01246 } \
01247 \
01248 for(int i = pkg->y1; i < pkg->y2; i++) \
01249 { \
01250 unsigned char *out_row = plugin->gradient->get_rows()[i]; \
01251 \
01252 switch(plugin->config.shape) \
01253 { \
01254 case TimeFrontConfig::LINEAR: \
01255 for(int j = 0; j < w; j++) \
01256 { \
01257 int x = j - half_w; \
01258 int y = -(i - half_h); \
01259 \
01260 \
01261 int input_y = (int)(gradient_size / 2 - \
01262 (x * sin_angle + y * cos_angle) + \
01263 0.5); \
01264 \
01265 \
01266 \
01267 if(input_y < 0) \
01268 { \
01269 out_row[0] = out4; \
01270 } \
01271 else \
01272 if(input_y >= gradient_size) \
01273 { \
01274 out_row[0] = in4; \
01275 } \
01276 else \
01277 { \
01278 out_row[0] = a_table[input_y]; \
01279 } \
01280 \
01281 out_row ++; \
01282 } \
01283 break; \
01284 \
01285 case TimeFrontConfig::RADIAL: \
01286 for(int j = 0; j < w; j++) \
01287 { \
01288 double x = j - center_x; \
01289 double y = i - center_y; \
01290 double magnitude = hypot(x, y); \
01291 int input_y = (int)magnitude; \
01292 out_row[0] = a_table[input_y]; \
01293 out_row ++; \
01294 } \
01295 break; \
01296 } \
01297 } \
01298 }
01299
01300 void TimeFrontUnit::process_package(LoadPackage *package)
01301 {
01302 TimeFrontPackage *pkg = (TimeFrontPackage*)package;
01303 int h = plugin->input->get_h();
01304 int w = plugin->input->get_w();
01305 int half_w = w / 2;
01306 int half_h = h / 2;
01307 int gradient_size = (int)(ceil(hypot(w, h)));
01308 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
01309 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
01310 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
01311 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
01312 double center_x = plugin->config.center_x * w / 100;
01313 double center_y = plugin->config.center_y * h / 100;
01314 unsigned char *a_table = 0;
01315
01316 if(in_radius > out_radius)
01317 {
01318 in_radius ^= out_radius;
01319 out_radius ^= in_radius;
01320 in_radius ^= out_radius;
01321 }
01322
01323
01324 int in4 = plugin->config.frame_range;
01325 int out4 = 0;
01326 CREATE_GRADIENT
01327
01328 if(a_table) free(a_table);
01329 }
01330
01331
01332
01333
01334
01335
01336 TimeFrontServer::TimeFrontServer(TimeFrontMain *plugin,
01337 int total_clients,
01338 int total_packages)
01339 : LoadServer(total_clients, total_packages)
01340 {
01341 this->plugin = plugin;
01342 }
01343
01344 void TimeFrontServer::init_packages()
01345 {
01346 for(int i = 0; i < get_total_packages(); i++)
01347 {
01348 TimeFrontPackage *package = (TimeFrontPackage*)get_package(i);
01349 package->y1 = plugin->input->get_h() *
01350 i /
01351 get_total_packages();
01352 package->y2 = plugin->input->get_h() *
01353 (i + 1) /
01354 get_total_packages();
01355 }
01356 }
01357
01358 LoadClient* TimeFrontServer::new_client()
01359 {
01360 return new TimeFrontUnit(this, plugin);
01361 }
01362
01363 LoadPackage* TimeFrontServer::new_package()
01364 {
01365 return new TimeFrontPackage;
01366 }
01367
01368
01369
01370
01371