1 #include "bcdisplayinfo.h"
9 #include "pluginvclient.h"
11 #include "transportque.inc"
19 class InterpolateVideo;
20 class InterpolateVideoWindow;
23 class InterpolateVideoConfig
26 InterpolateVideoConfig();
28 void copy_from(InterpolateVideoConfig *config);
29 int equivalent(InterpolateVideoConfig *config);
31 // Frame rate of input
33 // If 1, use the keyframes as beginning and end frames and ignore input rate
40 class InterpolateVideoRate : public BC_TextBox
43 InterpolateVideoRate(InterpolateVideo *plugin,
44 InterpolateVideoWindow *gui,
48 InterpolateVideo *plugin;
49 InterpolateVideoWindow *gui;
52 class InterpolateVideoRateMenu : public BC_ListBox
55 InterpolateVideoRateMenu(InterpolateVideo *plugin,
56 InterpolateVideoWindow *gui,
60 InterpolateVideo *plugin;
61 InterpolateVideoWindow *gui;
64 class InterpolateVideoKeyframes : public BC_CheckBox
67 InterpolateVideoKeyframes(InterpolateVideo *plugin,
68 InterpolateVideoWindow *gui,
72 InterpolateVideoWindow *gui;
73 InterpolateVideo *plugin;
76 class InterpolateVideoWindow : public BC_Window
79 InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y);
80 ~InterpolateVideoWindow();
82 void create_objects();
84 void update_enabled();
86 ArrayList<BC_ListBoxItem*> frame_rates;
87 InterpolateVideo *plugin;
89 InterpolateVideoRate *rate;
90 InterpolateVideoRateMenu *rate_menu;
91 InterpolateVideoKeyframes *keyframes;
95 PLUGIN_THREAD_HEADER(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
99 class InterpolateVideo : public PluginVClient
102 InterpolateVideo(PluginServer *server);
105 PLUGIN_CLASS_MEMBERS(InterpolateVideoConfig, InterpolateVideoThread)
107 int process_buffer(VFrame *frame,
108 int64_t start_position,
113 void save_data(KeyFrame *keyframe);
114 void read_data(KeyFrame *keyframe);
117 void fill_border(double frame_rate, int64_t start_position);
119 // beginning and end frames
121 // Last requested positions
122 int64_t frame_number[2];
123 // Last output position
124 int64_t last_position;
127 // Current requested positions
131 // Input rate determined by keyframe mode
132 double active_input_rate;
146 InterpolateVideoConfig::InterpolateVideoConfig()
148 input_rate = (double)30000 / 1001;
152 void InterpolateVideoConfig::copy_from(InterpolateVideoConfig *config)
154 this->input_rate = config->input_rate;
155 this->use_keyframes = config->use_keyframes;
158 int InterpolateVideoConfig::equivalent(InterpolateVideoConfig *config)
160 return EQUIV(this->input_rate, config->input_rate) &&
161 (this->use_keyframes == config->use_keyframes);
172 InterpolateVideoWindow::InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y)
173 : BC_Window(plugin->gui_string,
184 this->plugin = plugin;
187 InterpolateVideoWindow::~InterpolateVideoWindow()
191 void InterpolateVideoWindow::create_objects()
196 add_subwindow(title = new BC_Title(x, y, _("Input frames per second:")));
198 add_subwindow(rate = new InterpolateVideoRate(plugin,
202 add_subwindow(rate_menu = new InterpolateVideoRateMenu(plugin,
204 x + rate->get_w() + 5,
207 add_subwindow(keyframes = new InterpolateVideoKeyframes(plugin,
217 void InterpolateVideoWindow::update_enabled()
219 if(plugin->config.use_keyframes)
229 WINDOW_CLOSE_EVENT(InterpolateVideoWindow)
242 InterpolateVideoRate::InterpolateVideoRate(InterpolateVideo *plugin,
243 InterpolateVideoWindow *gui,
250 (float)plugin->config.input_rate)
252 this->plugin = plugin;
256 int InterpolateVideoRate::handle_event()
258 plugin->config.input_rate = Units::atoframerate(get_text());
259 plugin->send_configure_change();
266 InterpolateVideoRateMenu::InterpolateVideoRateMenu(InterpolateVideo *plugin,
267 InterpolateVideoWindow *gui,
275 &plugin->get_theme()->frame_rates,
282 this->plugin = plugin;
286 int InterpolateVideoRateMenu::handle_event()
288 char *text = get_selection(0, 0)->get_text();
289 plugin->config.input_rate = atof(text);
290 gui->rate->update(text);
291 plugin->send_configure_change();
298 InterpolateVideoKeyframes::InterpolateVideoKeyframes(InterpolateVideo *plugin,
299 InterpolateVideoWindow *gui,
304 plugin->config.use_keyframes,
305 _("Use keyframes as input"))
307 this->plugin = plugin;
310 int InterpolateVideoKeyframes::handle_event()
312 plugin->config.use_keyframes = get_value();
313 gui->update_enabled();
314 plugin->send_configure_change();
326 PLUGIN_THREAD_OBJECT(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
337 REGISTER_PLUGIN(InterpolateVideo)
344 InterpolateVideo::InterpolateVideo(PluginServer *server)
345 : PluginVClient(server)
347 PLUGIN_CONSTRUCTOR_MACRO
348 bzero(frames, sizeof(VFrame*) * 2);
349 for(int i = 0; i < 2; i++)
350 frame_number[i] = -1;
356 InterpolateVideo::~InterpolateVideo()
358 PLUGIN_DESTRUCTOR_MACRO
359 if(frames[0]) delete frames[0];
360 if(frames[1]) delete frames[1];
364 void InterpolateVideo::fill_border(double frame_rate, int64_t start_position)
366 // A border frame changed or the start position is identical to the last
368 if(range_start != frame_number[0] ||
369 last_position != start_position ||
370 !EQUIV(last_rate, frame_rate))
372 //printf("InterpolateVideo::fill_border 1 %lld\n", range_start);
373 read_frame(frames[0],
375 range_start + (get_direction() == PLAY_REVERSE ? 1 : 0),
379 if(range_end != frame_number[1] ||
380 last_position != start_position ||
381 !EQUIV(last_rate, frame_rate))
383 //printf("InterpolateVideo::fill_border 2 %lld\n", range_start);
384 read_frame(frames[1],
386 range_end + (get_direction() == PLAY_REVERSE ? 1 : 0),
390 last_position = start_position;
391 last_rate = frame_rate;
392 frame_number[0] = range_start;
393 frame_number[1] = range_end;
397 #define AVERAGE(type, temp_type,components, max) \
399 temp_type fraction0 = (temp_type)(lowest_fraction * max); \
400 temp_type fraction1 = (temp_type)(max - fraction0); \
402 for(int i = 0; i < h; i++) \
404 type *in_row0 = (type*)frames[0]->get_rows()[i]; \
405 type *in_row1 = (type*)frames[1]->get_rows()[i]; \
406 type *out_row = (type*)frame->get_rows()[i]; \
407 for(int j = 0; j < w * components; j++) \
409 *out_row++ = (*in_row0++ * fraction0 + *in_row1++ * fraction1) / max; \
418 int InterpolateVideo::process_buffer(VFrame *frame,
419 int64_t start_position,
422 if(get_direction() == PLAY_REVERSE) start_position--;
423 load_configuration();
427 for(int i = 0; i < 2; i++)
429 frames[i] = new VFrame(0,
432 frame->get_color_model(),
436 //printf("InterpolateVideo::process_buffer 1 %lld %lld\n", range_start, range_end);
438 if(range_start == range_end)
449 // Fill border frames
450 fill_border(frame_rate, start_position);
452 // Fraction of lowest frame in output
453 int64_t requested_range_start = (int64_t)((double)range_start *
456 int64_t requested_range_end = (int64_t)((double)range_end *
459 float highest_fraction = (float)(start_position - requested_range_start) /
460 (requested_range_end - requested_range_start);
462 // Fraction of highest frame in output
463 float lowest_fraction = 1.0 - highest_fraction;
464 CLAMP(highest_fraction, 0, 1);
465 CLAMP(lowest_fraction, 0, 1);
467 // printf("InterpolateVideo::process_buffer %lld %lld %lld %f %f %lld %lld %f %f\n",
470 // requested_range_start,
471 // requested_range_end,
473 // config.input_rate,
476 // highest_fraction);
478 int w = frame->get_w();
479 int h = frame->get_h();
480 switch(frame->get_color_model())
483 AVERAGE(float, float, 3, 1);
487 AVERAGE(unsigned char, int, 3, 0xff);
490 AVERAGE(float, float, 4, 1);
494 AVERAGE(unsigned char, int, 4, 0xff);
498 AVERAGE(uint16_t, int, 3, 0xffff);
500 case BC_RGBA16161616:
501 case BC_YUVA16161616:
502 AVERAGE(uint16_t, int, 4, 0xffff);
511 int InterpolateVideo::is_realtime()
516 char* InterpolateVideo::plugin_title()
518 return N_("Interpolate");
521 NEW_PICON_MACRO(InterpolateVideo)
523 SHOW_GUI_MACRO(InterpolateVideo, InterpolateVideoThread)
525 RAISE_WINDOW_MACRO(InterpolateVideo)
527 SET_STRING_MACRO(InterpolateVideo)
529 int InterpolateVideo::load_configuration()
531 KeyFrame *prev_keyframe, *next_keyframe;
532 InterpolateVideoConfig old_config;
533 old_config.copy_from(&config);
535 next_keyframe = get_next_keyframe(get_source_position());
536 prev_keyframe = get_prev_keyframe(get_source_position());
537 // Previous keyframe stays in config object.
538 read_data(prev_keyframe);
541 int64_t prev_position = edl_to_local(prev_keyframe->position);
542 int64_t next_position = edl_to_local(next_keyframe->position);
543 if(prev_position == 0 && next_position == 0)
545 next_position = prev_position = get_source_start();
547 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld\n",
548 // prev_keyframe->position,
549 // next_keyframe->position,
553 // Get range to average in requested rate
554 range_start = prev_position;
555 range_end = next_position;
558 // Use keyframes to determine range
559 if(config.use_keyframes)
561 active_input_rate = get_framerate();
562 // Between keyframe and edge of range or no keyframes
563 if(range_start == range_end)
565 // Between first keyframe and start of effect
566 if(get_source_position() >= get_source_start() &&
567 get_source_position() < range_start)
569 range_start = get_source_start();
572 // Between last keyframe and end of effect
573 if(get_source_position() >= range_start &&
574 get_source_position() < get_source_start() + get_total_len())
576 // Last frame should be inclusive of current effect
577 range_end = get_source_start() + get_total_len() - 1;
581 // Should never get here
587 // Make requested rate equal to input rate for this mode.
589 // Convert requested rate to input rate
590 // printf("InterpolateVideo::load_configuration 2 %lld %lld %f %f\n",
594 // config.input_rate);
595 // range_start = (int64_t)((double)range_start / get_framerate() * active_input_rate + 0.5);
596 // range_end = (int64_t)((double)range_end / get_framerate() * active_input_rate + 0.5);
601 active_input_rate = config.input_rate;
602 // Convert to input frame rate
603 range_start = (int64_t)(get_source_position() /
606 range_end = (int64_t)(get_source_position() /
608 active_input_rate) + 1;
611 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld %lld %lld\n",
612 // prev_keyframe->position,
613 // next_keyframe->position,
620 return !config.equivalent(&old_config);
623 int InterpolateVideo::load_defaults()
625 char directory[BCTEXTLEN];
626 // set the default directory
627 sprintf(directory, "%sinterpolatevideo.rc", BCASTDIR);
630 defaults = new Defaults(directory);
633 config.input_rate = defaults->get("INPUT_RATE", config.input_rate);
634 config.input_rate = Units::fix_framerate(config.input_rate);
635 config.use_keyframes = defaults->get("USE_KEYFRAMES", config.use_keyframes);
639 int InterpolateVideo::save_defaults()
641 defaults->update("INPUT_RATE", config.input_rate);
642 defaults->update("USE_KEYFRAMES", config.use_keyframes);
647 void InterpolateVideo::save_data(KeyFrame *keyframe)
651 // cause data to be stored directly in text
652 output.set_shared_string(keyframe->data, MESSAGESIZE);
653 output.tag.set_title("INTERPOLATEVIDEO");
654 output.tag.set_property("INPUT_RATE", config.input_rate);
655 output.tag.set_property("USE_KEYFRAMES", config.use_keyframes);
657 output.terminate_string();
660 void InterpolateVideo::read_data(KeyFrame *keyframe)
664 input.set_shared_string(keyframe->data, strlen(keyframe->data));
668 while(!input.read_tag())
670 if(input.tag.title_is("INTERPOLATEVIDEO"))
672 config.input_rate = input.tag.get_property("INPUT_RATE", config.input_rate);
673 config.input_rate = Units::fix_framerate(config.input_rate);
674 config.use_keyframes = input.tag.get_property("USE_KEYFRAMES", config.use_keyframes);
679 void InterpolateVideo::update_gui()
683 if(load_configuration())
685 thread->window->lock_window("InterpolateVideo::update_gui");
686 thread->window->rate->update((float)config.input_rate);
687 thread->window->keyframes->update(config.use_keyframes);
688 thread->window->update_enabled();
689 thread->window->unlock_window();