00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "keyframe.h"
00007 #include "language.h"
00008 #include "picon_png.h"
00009 #include "pluginvclient.h"
00010 #include "theme.h"
00011 #include "transportque.inc"
00012 #include "vframe.h"
00013
00014 #include <string.h>
00015 #include <stdint.h>
00016
00017
00018
00019 class InterpolateVideo;
00020 class InterpolateVideoWindow;
00021
00022
00023 class InterpolateVideoConfig
00024 {
00025 public:
00026 InterpolateVideoConfig();
00027
00028 void copy_from(InterpolateVideoConfig *config);
00029 int equivalent(InterpolateVideoConfig *config);
00030
00031
00032 double input_rate;
00033
00034 int use_keyframes;
00035 };
00036
00037
00038
00039
00040 class InterpolateVideoRate : public BC_TextBox
00041 {
00042 public:
00043 InterpolateVideoRate(InterpolateVideo *plugin,
00044 InterpolateVideoWindow *gui,
00045 int x,
00046 int y);
00047 int handle_event();
00048 InterpolateVideo *plugin;
00049 InterpolateVideoWindow *gui;
00050 };
00051
00052 class InterpolateVideoRateMenu : public BC_ListBox
00053 {
00054 public:
00055 InterpolateVideoRateMenu(InterpolateVideo *plugin,
00056 InterpolateVideoWindow *gui,
00057 int x,
00058 int y);
00059 int handle_event();
00060 InterpolateVideo *plugin;
00061 InterpolateVideoWindow *gui;
00062 };
00063
00064 class InterpolateVideoKeyframes : public BC_CheckBox
00065 {
00066 public:
00067 InterpolateVideoKeyframes(InterpolateVideo *plugin,
00068 InterpolateVideoWindow *gui,
00069 int x,
00070 int y);
00071 int handle_event();
00072 InterpolateVideoWindow *gui;
00073 InterpolateVideo *plugin;
00074 };
00075
00076 class InterpolateVideoWindow : public BC_Window
00077 {
00078 public:
00079 InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y);
00080 ~InterpolateVideoWindow();
00081
00082 void create_objects();
00083 int close_event();
00084 void update_enabled();
00085
00086 ArrayList<BC_ListBoxItem*> frame_rates;
00087 InterpolateVideo *plugin;
00088
00089 InterpolateVideoRate *rate;
00090 InterpolateVideoRateMenu *rate_menu;
00091 InterpolateVideoKeyframes *keyframes;
00092 };
00093
00094
00095 PLUGIN_THREAD_HEADER(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
00096
00097
00098
00099 class InterpolateVideo : public PluginVClient
00100 {
00101 public:
00102 InterpolateVideo(PluginServer *server);
00103 ~InterpolateVideo();
00104
00105 PLUGIN_CLASS_MEMBERS(InterpolateVideoConfig, InterpolateVideoThread)
00106
00107 int process_buffer(VFrame *frame,
00108 int64_t start_position,
00109 double frame_rate);
00110 int is_realtime();
00111 int load_defaults();
00112 int save_defaults();
00113 void save_data(KeyFrame *keyframe);
00114 void read_data(KeyFrame *keyframe);
00115 void update_gui();
00116
00117 void fill_border(double frame_rate, int64_t start_position);
00118
00119
00120 VFrame *frames[2];
00121
00122 int64_t frame_number[2];
00123
00124 int64_t last_position;
00125 double last_rate;
00126
00127
00128 int64_t range_start;
00129 int64_t range_end;
00130
00131
00132 double active_input_rate;
00133 };
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 InterpolateVideoConfig::InterpolateVideoConfig()
00147 {
00148 input_rate = (double)30000 / 1001;
00149 use_keyframes = 0;
00150 }
00151
00152 void InterpolateVideoConfig::copy_from(InterpolateVideoConfig *config)
00153 {
00154 this->input_rate = config->input_rate;
00155 this->use_keyframes = config->use_keyframes;
00156 }
00157
00158 int InterpolateVideoConfig::equivalent(InterpolateVideoConfig *config)
00159 {
00160 return EQUIV(this->input_rate, config->input_rate) &&
00161 (this->use_keyframes == config->use_keyframes);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 InterpolateVideoWindow::InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y)
00173 : BC_Window(plugin->gui_string,
00174 x,
00175 y,
00176 210,
00177 160,
00178 200,
00179 160,
00180 0,
00181 0,
00182 1)
00183 {
00184 this->plugin = plugin;
00185 }
00186
00187 InterpolateVideoWindow::~InterpolateVideoWindow()
00188 {
00189 }
00190
00191 void InterpolateVideoWindow::create_objects()
00192 {
00193 int x = 10, y = 10;
00194
00195 BC_Title *title;
00196 add_subwindow(title = new BC_Title(x, y, _("Input frames per second:")));
00197 y += 30;
00198 add_subwindow(rate = new InterpolateVideoRate(plugin,
00199 this,
00200 x,
00201 y));
00202 add_subwindow(rate_menu = new InterpolateVideoRateMenu(plugin,
00203 this,
00204 x + rate->get_w() + 5,
00205 y));
00206 y += 30;
00207 add_subwindow(keyframes = new InterpolateVideoKeyframes(plugin,
00208 this,
00209 x,
00210 y));
00211
00212 update_enabled();
00213 show_window();
00214 flush();
00215 }
00216
00217 void InterpolateVideoWindow::update_enabled()
00218 {
00219 if(plugin->config.use_keyframes)
00220 {
00221 rate->disable();
00222 }
00223 else
00224 {
00225 rate->enable();
00226 }
00227 }
00228
00229 WINDOW_CLOSE_EVENT(InterpolateVideoWindow)
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 InterpolateVideoRate::InterpolateVideoRate(InterpolateVideo *plugin,
00243 InterpolateVideoWindow *gui,
00244 int x,
00245 int y)
00246 : BC_TextBox(x,
00247 y,
00248 90,
00249 1,
00250 (float)plugin->config.input_rate)
00251 {
00252 this->plugin = plugin;
00253 this->gui = gui;
00254 }
00255
00256 int InterpolateVideoRate::handle_event()
00257 {
00258 plugin->config.input_rate = Units::atoframerate(get_text());
00259 plugin->send_configure_change();
00260 return 1;
00261 }
00262
00263
00264
00265
00266 InterpolateVideoRateMenu::InterpolateVideoRateMenu(InterpolateVideo *plugin,
00267 InterpolateVideoWindow *gui,
00268 int x,
00269 int y)
00270 : BC_ListBox(x,
00271 y,
00272 100,
00273 200,
00274 LISTBOX_TEXT,
00275 &plugin->get_theme()->frame_rates,
00276 0,
00277 0,
00278 1,
00279 0,
00280 1)
00281 {
00282 this->plugin = plugin;
00283 this->gui = gui;
00284 }
00285
00286 int InterpolateVideoRateMenu::handle_event()
00287 {
00288 char *text = get_selection(0, 0)->get_text();
00289 plugin->config.input_rate = atof(text);
00290 gui->rate->update(text);
00291 plugin->send_configure_change();
00292 return 1;
00293 }
00294
00295
00296
00297
00298 InterpolateVideoKeyframes::InterpolateVideoKeyframes(InterpolateVideo *plugin,
00299 InterpolateVideoWindow *gui,
00300 int x,
00301 int y)
00302 : BC_CheckBox(x,
00303 y,
00304 plugin->config.use_keyframes,
00305 _("Use keyframes as input"))
00306 {
00307 this->plugin = plugin;
00308 this->gui = gui;
00309 }
00310 int InterpolateVideoKeyframes::handle_event()
00311 {
00312 plugin->config.use_keyframes = get_value();
00313 gui->update_enabled();
00314 plugin->send_configure_change();
00315 return 1;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 PLUGIN_THREAD_OBJECT(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 REGISTER_PLUGIN(InterpolateVideo)
00338
00339
00340
00341
00342
00343
00344 InterpolateVideo::InterpolateVideo(PluginServer *server)
00345 : PluginVClient(server)
00346 {
00347 PLUGIN_CONSTRUCTOR_MACRO
00348 bzero(frames, sizeof(VFrame*) * 2);
00349 for(int i = 0; i < 2; i++)
00350 frame_number[i] = -1;
00351 last_position = -1;
00352 last_rate = -1;
00353 }
00354
00355
00356 InterpolateVideo::~InterpolateVideo()
00357 {
00358 PLUGIN_DESTRUCTOR_MACRO
00359 if(frames[0]) delete frames[0];
00360 if(frames[1]) delete frames[1];
00361 }
00362
00363
00364 void InterpolateVideo::fill_border(double frame_rate, int64_t start_position)
00365 {
00366
00367
00368 if(range_start != frame_number[0] ||
00369 last_position != start_position ||
00370 !EQUIV(last_rate, frame_rate))
00371 {
00372
00373 read_frame(frames[0],
00374 0,
00375 range_start + (get_direction() == PLAY_REVERSE ? 1 : 0),
00376 active_input_rate);
00377 }
00378
00379 if(range_end != frame_number[1] ||
00380 last_position != start_position ||
00381 !EQUIV(last_rate, frame_rate))
00382 {
00383
00384 read_frame(frames[1],
00385 0,
00386 range_end + (get_direction() == PLAY_REVERSE ? 1 : 0),
00387 active_input_rate);
00388 }
00389
00390 last_position = start_position;
00391 last_rate = frame_rate;
00392 frame_number[0] = range_start;
00393 frame_number[1] = range_end;
00394 }
00395
00396
00397 #define AVERAGE(type, temp_type,components, max) \
00398 { \
00399 temp_type fraction0 = (temp_type)(lowest_fraction * max); \
00400 temp_type fraction1 = (temp_type)(max - fraction0); \
00401 \
00402 for(int i = 0; i < h; i++) \
00403 { \
00404 type *in_row0 = (type*)frames[0]->get_rows()[i]; \
00405 type *in_row1 = (type*)frames[1]->get_rows()[i]; \
00406 type *out_row = (type*)frame->get_rows()[i]; \
00407 for(int j = 0; j < w * components; j++) \
00408 { \
00409 *out_row++ = (*in_row0++ * fraction0 + *in_row1++ * fraction1) / max; \
00410 } \
00411 } \
00412 }
00413
00414
00415
00416
00417
00418 int InterpolateVideo::process_buffer(VFrame *frame,
00419 int64_t start_position,
00420 double frame_rate)
00421 {
00422 if(get_direction() == PLAY_REVERSE) start_position--;
00423 load_configuration();
00424
00425 if(!frames[0])
00426 {
00427 for(int i = 0; i < 2; i++)
00428 {
00429 frames[i] = new VFrame(0,
00430 frame->get_w(),
00431 frame->get_h(),
00432 frame->get_color_model(),
00433 -1);
00434 }
00435 }
00436
00437
00438 if(range_start == range_end)
00439 {
00440 read_frame(frame,
00441 0,
00442 range_start,
00443 active_input_rate);
00444 return 0;
00445 }
00446 else
00447 {
00448
00449
00450 fill_border(frame_rate, start_position);
00451
00452
00453 int64_t requested_range_start = (int64_t)((double)range_start *
00454 frame_rate /
00455 active_input_rate);
00456 int64_t requested_range_end = (int64_t)((double)range_end *
00457 frame_rate /
00458 active_input_rate);
00459 float highest_fraction = (float)(start_position - requested_range_start) /
00460 (requested_range_end - requested_range_start);
00461
00462
00463 float lowest_fraction = 1.0 - highest_fraction;
00464 CLAMP(highest_fraction, 0, 1);
00465 CLAMP(lowest_fraction, 0, 1);
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 int w = frame->get_w();
00479 int h = frame->get_h();
00480 switch(frame->get_color_model())
00481 {
00482 case BC_RGB_FLOAT:
00483 AVERAGE(float, float, 3, 1);
00484 break;
00485 case BC_RGB888:
00486 case BC_YUV888:
00487 AVERAGE(unsigned char, int, 3, 0xff);
00488 break;
00489 case BC_RGBA_FLOAT:
00490 AVERAGE(float, float, 4, 1);
00491 break;
00492 case BC_RGBA8888:
00493 case BC_YUVA8888:
00494 AVERAGE(unsigned char, int, 4, 0xff);
00495 break;
00496 case BC_RGB161616:
00497 case BC_YUV161616:
00498 AVERAGE(uint16_t, int, 3, 0xffff);
00499 break;
00500 case BC_RGBA16161616:
00501 case BC_YUVA16161616:
00502 AVERAGE(uint16_t, int, 4, 0xffff);
00503 break;
00504 }
00505 }
00506 return 0;
00507 }
00508
00509
00510
00511 int InterpolateVideo::is_realtime()
00512 {
00513 return 1;
00514 }
00515
00516 char* InterpolateVideo::plugin_title()
00517 {
00518 return N_("Interpolate");
00519 }
00520
00521 NEW_PICON_MACRO(InterpolateVideo)
00522
00523 SHOW_GUI_MACRO(InterpolateVideo, InterpolateVideoThread)
00524
00525 RAISE_WINDOW_MACRO(InterpolateVideo)
00526
00527 SET_STRING_MACRO(InterpolateVideo)
00528
00529 int InterpolateVideo::load_configuration()
00530 {
00531 KeyFrame *prev_keyframe, *next_keyframe;
00532 InterpolateVideoConfig old_config;
00533 old_config.copy_from(&config);
00534
00535 next_keyframe = get_next_keyframe(get_source_position());
00536 prev_keyframe = get_prev_keyframe(get_source_position());
00537
00538 read_data(prev_keyframe);
00539
00540
00541 int64_t prev_position = edl_to_local(prev_keyframe->position);
00542 int64_t next_position = edl_to_local(next_keyframe->position);
00543 if(prev_position == 0 && next_position == 0)
00544 {
00545 next_position = prev_position = get_source_start();
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 range_start = prev_position;
00555 range_end = next_position;
00556
00557
00558
00559 if(config.use_keyframes)
00560 {
00561 active_input_rate = get_framerate();
00562
00563 if(range_start == range_end)
00564 {
00565
00566 if(get_source_position() >= get_source_start() &&
00567 get_source_position() < range_start)
00568 {
00569 range_start = get_source_start();
00570 }
00571 else
00572
00573 if(get_source_position() >= range_start &&
00574 get_source_position() < get_source_start() + get_total_len())
00575 {
00576
00577 range_end = get_source_start() + get_total_len() - 1;
00578 }
00579 else
00580 {
00581
00582 ;
00583 }
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 }
00598 else
00599
00600 {
00601 active_input_rate = config.input_rate;
00602
00603 range_start = (int64_t)(get_source_position() /
00604 get_framerate() *
00605 active_input_rate);
00606 range_end = (int64_t)(get_source_position() /
00607 get_framerate() *
00608 active_input_rate) + 1;
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 return !config.equivalent(&old_config);
00621 }
00622
00623 int InterpolateVideo::load_defaults()
00624 {
00625 char directory[BCTEXTLEN];
00626
00627 sprintf(directory, "%sinterpolatevideo.rc", BCASTDIR);
00628
00629
00630 defaults = new BC_Hash(directory);
00631 defaults->load();
00632
00633 config.input_rate = defaults->get("INPUT_RATE", config.input_rate);
00634 config.input_rate = Units::fix_framerate(config.input_rate);
00635 config.use_keyframes = defaults->get("USE_KEYFRAMES", config.use_keyframes);
00636 return 0;
00637 }
00638
00639 int InterpolateVideo::save_defaults()
00640 {
00641 defaults->update("INPUT_RATE", config.input_rate);
00642 defaults->update("USE_KEYFRAMES", config.use_keyframes);
00643 defaults->save();
00644 return 0;
00645 }
00646
00647 void InterpolateVideo::save_data(KeyFrame *keyframe)
00648 {
00649 FileXML output;
00650
00651
00652 output.set_shared_string(keyframe->data, MESSAGESIZE);
00653 output.tag.set_title("INTERPOLATEVIDEO");
00654 output.tag.set_property("INPUT_RATE", config.input_rate);
00655 output.tag.set_property("USE_KEYFRAMES", config.use_keyframes);
00656 output.append_tag();
00657 output.tag.set_title("/INTERPOLATEVIDEO");
00658 output.append_tag();
00659 output.terminate_string();
00660 }
00661
00662 void InterpolateVideo::read_data(KeyFrame *keyframe)
00663 {
00664 FileXML input;
00665
00666 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00667
00668 int result = 0;
00669
00670 while(!input.read_tag())
00671 {
00672 if(input.tag.title_is("INTERPOLATEVIDEO"))
00673 {
00674 config.input_rate = input.tag.get_property("INPUT_RATE", config.input_rate);
00675 config.input_rate = Units::fix_framerate(config.input_rate);
00676 config.use_keyframes = input.tag.get_property("USE_KEYFRAMES", config.use_keyframes);
00677 }
00678 }
00679 }
00680
00681 void InterpolateVideo::update_gui()
00682 {
00683 if(thread)
00684 {
00685 if(load_configuration())
00686 {
00687 thread->window->lock_window("InterpolateVideo::update_gui");
00688 thread->window->rate->update((float)config.input_rate);
00689 thread->window->keyframes->update(config.use_keyframes);
00690 thread->window->update_enabled();
00691 thread->window->unlock_window();
00692 }
00693 }
00694 }
00695
00696