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 "pluginvclient.h"
00008 #include "transportque.h"
00009
00010 #include <string.h>
00011
00012 class ReframeRT;
00013 class ReframeRTWindow;
00014
00015 class ReframeRTConfig
00016 {
00017 public:
00018 ReframeRTConfig();
00019 void boundaries();
00020 int equivalent(ReframeRTConfig &src);
00021 void copy_from(ReframeRTConfig &src);
00022 void interpolate(ReframeRTConfig &prev,
00023 ReframeRTConfig &next,
00024 int64_t prev_frame,
00025 int64_t next_frame,
00026 int64_t current_frame);
00027 double scale;
00028 int stretch;
00029 int interp;
00030 };
00031
00032
00033 class ReframeRTScale : public BC_TumbleTextBox
00034 {
00035 public:
00036 ReframeRTScale(ReframeRT *plugin,
00037 ReframeRTWindow *gui,
00038 int x,
00039 int y);
00040 int handle_event();
00041 ReframeRT *plugin;
00042 };
00043
00044 class ReframeRTStretch : public BC_Radial
00045 {
00046 public:
00047 ReframeRTStretch(ReframeRT *plugin,
00048 ReframeRTWindow *gui,
00049 int x,
00050 int y);
00051 int handle_event();
00052 ReframeRT *plugin;
00053 ReframeRTWindow *gui;
00054 };
00055
00056 class ReframeRTDownsample : public BC_Radial
00057 {
00058 public:
00059 ReframeRTDownsample(ReframeRT *plugin,
00060 ReframeRTWindow *gui,
00061 int x,
00062 int y);
00063 int handle_event();
00064 ReframeRT *plugin;
00065 ReframeRTWindow *gui;
00066 };
00067
00068 class ReframeRTInterpolate : public BC_CheckBox
00069 {
00070 public:
00071 ReframeRTInterpolate(ReframeRT *plugin,
00072 ReframeRTWindow *gui,
00073 int x,
00074 int y);
00075 int handle_event();
00076 ReframeRT *plugin;
00077 ReframeRTWindow *gui;
00078 };
00079
00080 class ReframeRTWindow : public BC_Window
00081 {
00082 public:
00083 ReframeRTWindow(ReframeRT *plugin, int x, int y);
00084 ~ReframeRTWindow();
00085 void create_objects();
00086 int close_event();
00087 ReframeRT *plugin;
00088 ReframeRTScale *scale;
00089 ReframeRTStretch *stretch;
00090 ReframeRTDownsample *downsample;
00091 ReframeRTInterpolate *interpolate;
00092 };
00093
00094 PLUGIN_THREAD_HEADER(ReframeRT, ReframeRTThread, ReframeRTWindow)
00095
00096 class ReframeRT : public PluginVClient
00097 {
00098 public:
00099 ReframeRT(PluginServer *server);
00100 ~ReframeRT();
00101
00102 PLUGIN_CLASS_MEMBERS(ReframeRTConfig, ReframeRTThread)
00103
00104 int load_defaults();
00105 int save_defaults();
00106 void save_data(KeyFrame *keyframe);
00107 void read_data(KeyFrame *keyframe);
00108 void update_gui();
00109 int is_realtime();
00110 int is_synthesis();
00111 int process_buffer(VFrame *frame,
00112 int64_t start_position,
00113 double frame_rate);
00114 };
00115
00116
00117
00118
00119
00120
00121
00122 REGISTER_PLUGIN(ReframeRT);
00123
00124
00125
00126 ReframeRTConfig::ReframeRTConfig()
00127 {
00128 scale = 1.0;
00129 stretch = 0;
00130 interp = 0;
00131 }
00132
00133 int ReframeRTConfig::equivalent(ReframeRTConfig &src)
00134 {
00135 return fabs(scale - src.scale) < 0.0001 &&
00136 stretch == src.stretch &&
00137 interp == src.interp;
00138 }
00139
00140 void ReframeRTConfig::copy_from(ReframeRTConfig &src)
00141 {
00142 this->scale = src.scale;
00143 this->stretch = src.stretch;
00144 this->interp = src.interp;
00145 }
00146
00147 void ReframeRTConfig::interpolate(ReframeRTConfig &prev,
00148 ReframeRTConfig &next,
00149 int64_t prev_frame,
00150 int64_t next_frame,
00151 int64_t current_frame)
00152 {
00153 this->interp = prev.interp;
00154 this->stretch = prev.stretch;
00155
00156 if (this->interp && prev_frame != next_frame)
00157 {
00158
00159 double slope = (next.scale - prev.scale) / (next_frame - prev_frame);
00160 this->scale = (slope * (current_frame - prev_frame)) + prev.scale;
00161 }
00162 else
00163 {
00164 this->scale = prev.scale;
00165 }
00166 }
00167
00168 void ReframeRTConfig::boundaries()
00169 {
00170 if(fabs(scale) < 0.0001) scale = 0.0001;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180 ReframeRTWindow::ReframeRTWindow(ReframeRT *plugin, int x, int y)
00181 : BC_Window(plugin->gui_string,
00182 x,
00183 y,
00184 210,
00185 160,
00186 200,
00187 160,
00188 0,
00189 0,
00190 1)
00191 {
00192 this->plugin = plugin;
00193 }
00194
00195 ReframeRTWindow::~ReframeRTWindow()
00196 {
00197 }
00198
00199 void ReframeRTWindow::create_objects()
00200 {
00201 int x = 10, y = 10;
00202
00203 add_subwindow(new BC_Title(x, y, _("Scale by amount:")));
00204 y += 20;
00205 scale = new ReframeRTScale(plugin,
00206 this,
00207 x,
00208 y);
00209 scale->create_objects();
00210 scale->set_increment(0.1);
00211 y += 30;
00212 add_subwindow(stretch = new ReframeRTStretch(plugin,
00213 this,
00214 x,
00215 y));
00216 y += 30;
00217 add_subwindow(downsample = new ReframeRTDownsample(plugin,
00218 this,
00219 x,
00220 y));
00221 y += 30;
00222 add_subwindow(interpolate = new ReframeRTInterpolate(plugin,
00223 this,
00224 x,
00225 y));
00226 show_window();
00227 flush();
00228 }
00229
00230 WINDOW_CLOSE_EVENT(ReframeRTWindow)
00231
00232
00233 PLUGIN_THREAD_OBJECT(ReframeRT, ReframeRTThread, ReframeRTWindow)
00234
00235
00236
00237
00238
00239
00240 ReframeRTScale::ReframeRTScale(ReframeRT *plugin,
00241 ReframeRTWindow *gui,
00242 int x,
00243 int y)
00244 : BC_TumbleTextBox(gui,
00245 (float)plugin->config.scale,
00246 (float)-1000,
00247 (float)1000,
00248 x,
00249 y,
00250 100)
00251 {
00252 this->plugin = plugin;
00253 }
00254
00255 int ReframeRTScale::handle_event()
00256 {
00257 plugin->config.scale = atof(get_text());
00258 plugin->config.boundaries();
00259 plugin->send_configure_change();
00260 return 1;
00261 }
00262
00263 ReframeRTStretch::ReframeRTStretch(ReframeRT *plugin,
00264 ReframeRTWindow *gui,
00265 int x,
00266 int y)
00267 : BC_Radial(x, y, plugin->config.stretch, _("Stretch"))
00268 {
00269 this->plugin = plugin;
00270 this->gui = gui;
00271 }
00272
00273 int ReframeRTStretch::handle_event()
00274 {
00275 plugin->config.stretch = get_value();
00276 gui->downsample->update(!get_value());
00277 plugin->send_configure_change();
00278 return 1;
00279 }
00280
00281
00282 ReframeRTDownsample::ReframeRTDownsample(ReframeRT *plugin,
00283 ReframeRTWindow *gui,
00284 int x,
00285 int y)
00286 : BC_Radial(x, y, !plugin->config.stretch, _("Downsample"))
00287 {
00288 this->plugin = plugin;
00289 this->gui = gui;
00290 }
00291
00292 int ReframeRTDownsample::handle_event()
00293 {
00294 plugin->config.stretch = !get_value();
00295 gui->stretch->update(!get_value());
00296 plugin->send_configure_change();
00297 return 1;
00298 }
00299
00300 ReframeRTInterpolate::ReframeRTInterpolate(ReframeRT *plugin,
00301 ReframeRTWindow *gui,
00302 int x,
00303 int y)
00304 : BC_CheckBox(x, y, 0, _("Interpolate"))
00305 {
00306 this->plugin = plugin;
00307 this->gui = gui;
00308 }
00309
00310 int ReframeRTInterpolate::handle_event()
00311 {
00312 plugin->config.interp = get_value();
00313 gui->interpolate->update(get_value());
00314 plugin->send_configure_change();
00315 return 1;
00316 }
00317
00318
00319
00320
00321 ReframeRT::ReframeRT(PluginServer *server)
00322 : PluginVClient(server)
00323 {
00324 PLUGIN_CONSTRUCTOR_MACRO
00325 }
00326
00327
00328 ReframeRT::~ReframeRT()
00329 {
00330 PLUGIN_DESTRUCTOR_MACRO
00331 }
00332
00333 char* ReframeRT::plugin_title() { return N_("ReframeRT"); }
00334 int ReframeRT::is_realtime() { return 1; }
00335 int ReframeRT::is_synthesis() { return 1; }
00336
00337 #include "picon_png.h"
00338 NEW_PICON_MACRO(ReframeRT)
00339
00340 SHOW_GUI_MACRO(ReframeRT, ReframeRTThread)
00341
00342 RAISE_WINDOW_MACRO(ReframeRT)
00343
00344 SET_STRING_MACRO(ReframeRT)
00345
00346 LOAD_CONFIGURATION_MACRO(ReframeRT, ReframeRTConfig)
00347
00348 int ReframeRT::process_buffer(VFrame *frame,
00349 int64_t start_position,
00350 double frame_rate)
00351 {
00352 int64_t input_frame = get_source_start();
00353 ReframeRTConfig prev_config, next_config;
00354 KeyFrame *tmp_keyframe, *next_keyframe = get_prev_keyframe(get_source_start());
00355 int64_t tmp_position, next_position;
00356 int64_t segment_len;
00357 double input_rate = frame_rate;
00358 int is_current_keyframe;
00359
00360
00361
00362
00363 KeyFrame *fake_keyframe = new KeyFrame();
00364 fake_keyframe->copy_from(next_keyframe);
00365 fake_keyframe->position = local_to_edl(get_source_start());
00366 next_keyframe = fake_keyframe;
00367
00368
00369 do
00370 {
00371 tmp_keyframe = next_keyframe;
00372 next_keyframe = get_next_keyframe(tmp_keyframe->position+1, 0);
00373
00374 tmp_position = edl_to_local(tmp_keyframe->position);
00375 next_position = edl_to_local(next_keyframe->position);
00376
00377 is_current_keyframe =
00378 next_position > start_position
00379 || next_keyframe->position == tmp_keyframe->position
00380 || !next_keyframe->position;
00381
00382 if (is_current_keyframe)
00383 segment_len = start_position - tmp_position;
00384 else
00385 segment_len = next_position - tmp_position;
00386
00387 read_data(next_keyframe);
00388 next_config.copy_from(config);
00389 read_data(tmp_keyframe);
00390 prev_config.copy_from(config);
00391 config.interpolate(prev_config, next_config, tmp_position, next_position, tmp_position + segment_len);
00392
00393
00394
00395
00396 input_frame += (int64_t)(segment_len * ((prev_config.scale + config.scale) / 2));
00397 } while (!is_current_keyframe);
00398
00399
00400 if (!config.stretch)
00401 input_rate *= config.scale;
00402
00403 read_frame(frame,
00404 0,
00405 input_frame,
00406 input_rate);
00407
00408 delete fake_keyframe;
00409
00410 return 0;
00411 }
00412
00413
00414
00415
00416
00417 int ReframeRT::load_defaults()
00418 {
00419 char directory[BCTEXTLEN];
00420
00421 sprintf(directory, "%sreframert.rc", BCASTDIR);
00422
00423
00424 defaults = new BC_Hash(directory);
00425 defaults->load();
00426
00427 config.scale = defaults->get("SCALE", config.scale);
00428 config.stretch = defaults->get("STRETCH", config.stretch);
00429 config.interp = defaults->get("INTERPOLATE", config.interp);
00430 return 0;
00431 }
00432
00433 int ReframeRT::save_defaults()
00434 {
00435 defaults->update("SCALE", config.scale);
00436 defaults->update("STRETCH", config.stretch);
00437 defaults->update("INTERPOLATE", config.interp);
00438 defaults->save();
00439 return 0;
00440 }
00441
00442 void ReframeRT::save_data(KeyFrame *keyframe)
00443 {
00444 FileXML output;
00445
00446
00447 output.set_shared_string(keyframe->data, MESSAGESIZE);
00448 output.tag.set_title("REFRAMERT");
00449 output.tag.set_property("SCALE", config.scale);
00450 output.tag.set_property("STRETCH", config.stretch);
00451 output.tag.set_property("INTERPOLATE", config.interp);
00452 output.append_tag();
00453 output.tag.set_title("/REFRAMERT");
00454 output.append_tag();
00455 output.terminate_string();
00456 }
00457
00458 void ReframeRT::read_data(KeyFrame *keyframe)
00459 {
00460 FileXML input;
00461
00462 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00463
00464 int result = 0;
00465
00466 while(!input.read_tag())
00467 {
00468 if(input.tag.title_is("REFRAMERT"))
00469 {
00470 config.scale = input.tag.get_property("SCALE", config.scale);
00471 config.stretch = input.tag.get_property("STRETCH", config.stretch);
00472 config.interp = input.tag.get_property("INTERPOLATE", config.interp);
00473 }
00474 }
00475 }
00476
00477 void ReframeRT::update_gui()
00478 {
00479 if(thread)
00480 {
00481 int changed = load_configuration();
00482
00483 if(changed)
00484 {
00485 thread->window->lock_window("ReframeRT::update_gui");
00486 thread->window->scale->update((float)config.scale);
00487 thread->window->stretch->update(config.stretch);
00488 thread->window->downsample->update(!config.stretch);
00489 thread->window->interpolate->update(config.interp);
00490 thread->window->unlock_window();
00491 }
00492 }
00493 }
00494
00495
00496
00497
00498