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,
71 InterpolateVideo *plugin;
74 class InterpolateVideoWindow : public BC_Window
77 InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y);
78 ~InterpolateVideoWindow();
80 void create_objects();
83 ArrayList<BC_ListBoxItem*> frame_rates;
84 InterpolateVideo *plugin;
86 InterpolateVideoRate *rate;
87 InterpolateVideoRateMenu *rate_menu;
88 InterpolateVideoKeyframes *keyframes;
92 PLUGIN_THREAD_HEADER(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
96 class InterpolateVideo : public PluginVClient
99 InterpolateVideo(PluginServer *server);
102 PLUGIN_CLASS_MEMBERS(InterpolateVideoConfig, InterpolateVideoThread)
104 int process_buffer(VFrame *frame,
105 int64_t start_position,
110 void save_data(KeyFrame *keyframe);
111 void read_data(KeyFrame *keyframe);
114 void fill_border(double frame_rate, int64_t start_position);
116 // beginning and end frames
118 // Last requested positions
119 int64_t frame_number[2];
120 // Last output position
121 int64_t last_position;
124 // Current requested positions
141 InterpolateVideoConfig::InterpolateVideoConfig()
143 input_rate = (double)30000 / 1001;
147 void InterpolateVideoConfig::copy_from(InterpolateVideoConfig *config)
149 this->input_rate = config->input_rate;
150 this->use_keyframes = config->use_keyframes;
153 int InterpolateVideoConfig::equivalent(InterpolateVideoConfig *config)
155 return EQUIV(this->input_rate, config->input_rate) &&
156 (this->use_keyframes == config->use_keyframes);
167 InterpolateVideoWindow::InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y)
168 : BC_Window(plugin->gui_string,
179 this->plugin = plugin;
182 InterpolateVideoWindow::~InterpolateVideoWindow()
186 void InterpolateVideoWindow::create_objects()
191 add_subwindow(title = new BC_Title(x, y, "Input frames per second:"));
193 add_subwindow(rate = new InterpolateVideoRate(plugin,
197 add_subwindow(rate_menu = new InterpolateVideoRateMenu(plugin,
199 x + rate->get_w() + 5,
202 add_subwindow(keyframes = new InterpolateVideoKeyframes(plugin,
210 WINDOW_CLOSE_EVENT(InterpolateVideoWindow)
223 InterpolateVideoRate::InterpolateVideoRate(InterpolateVideo *plugin,
224 InterpolateVideoWindow *gui,
231 (float)plugin->config.input_rate)
233 this->plugin = plugin;
237 int InterpolateVideoRate::handle_event()
239 plugin->config.input_rate = Units::atoframerate(get_text());
240 plugin->send_configure_change();
247 InterpolateVideoRateMenu::InterpolateVideoRateMenu(InterpolateVideo *plugin,
248 InterpolateVideoWindow *gui,
256 &plugin->get_theme()->frame_rates,
263 this->plugin = plugin;
267 int InterpolateVideoRateMenu::handle_event()
269 char *text = get_selection(0, 0)->get_text();
270 plugin->config.input_rate = atof(text);
271 gui->rate->update(text);
272 plugin->send_configure_change();
279 InterpolateVideoKeyframes::InterpolateVideoKeyframes(InterpolateVideo *plugin,
284 plugin->config.use_keyframes,
285 "Use keyframes as input")
287 this->plugin = plugin;
289 int InterpolateVideoKeyframes::handle_event()
291 plugin->config.use_keyframes = get_value();
292 plugin->send_configure_change();
304 PLUGIN_THREAD_OBJECT(InterpolateVideo, InterpolateVideoThread, InterpolateVideoWindow)
315 REGISTER_PLUGIN(InterpolateVideo)
322 InterpolateVideo::InterpolateVideo(PluginServer *server)
323 : PluginVClient(server)
325 PLUGIN_CONSTRUCTOR_MACRO
326 bzero(frames, sizeof(VFrame*) * 2);
327 for(int i = 0; i < 2; i++)
328 frame_number[i] = -1;
334 InterpolateVideo::~InterpolateVideo()
336 PLUGIN_DESTRUCTOR_MACRO
337 if(frames[0]) delete frames[0];
338 if(frames[1]) delete frames[1];
342 void InterpolateVideo::fill_border(double frame_rate, int64_t start_position)
344 // A border frame changed or the start position is identical to the last
346 if(range_start != frame_number[0] ||
347 last_position != start_position ||
348 !EQUIV(last_rate, frame_rate))
350 read_frame(frames[0],
352 range_start + (get_direction() == PLAY_REVERSE ? 1 : 0),
356 if(range_end != frame_number[1] ||
357 last_position != start_position ||
358 !EQUIV(last_rate, frame_rate))
360 read_frame(frames[1],
362 range_end + (get_direction() == PLAY_REVERSE ? 1 : 0),
366 last_position = start_position;
367 last_rate = frame_rate;
368 frame_number[0] = range_start;
369 frame_number[1] = range_end;
373 #define AVERAGE(type, temp_type,components, max) \
375 temp_type fraction0 = (temp_type)(lowest_fraction * max); \
376 temp_type fraction1 = (temp_type)(max - fraction0); \
378 for(int i = 0; i < h; i++) \
380 type *in_row0 = (type*)frames[0]->get_rows()[i]; \
381 type *in_row1 = (type*)frames[1]->get_rows()[i]; \
382 type *out_row = (type*)frame->get_rows()[i]; \
383 for(int j = 0; j < w * components; j++) \
385 *out_row++ = (*in_row0++ * fraction0 + *in_row1++ * fraction1) / max; \
394 int InterpolateVideo::process_buffer(VFrame *frame,
395 int64_t start_position,
398 if(get_direction() == PLAY_REVERSE) start_position--;
399 load_configuration();
403 for(int i = 0; i < 2; i++)
405 frames[i] = new VFrame(0,
408 frame->get_color_model(),
414 if(range_start == range_end)
425 // Fill border frames
426 fill_border(frame_rate, start_position);
428 // Fraction of lowest frame in output
429 int64_t requested_range_start = (int64_t)((double)range_start *
432 int64_t requested_range_end = (int64_t)((double)range_end *
435 float highest_fraction = (float)(start_position - requested_range_start) /
436 (requested_range_end - requested_range_start);
438 // Fraction of highest frame in output
439 float lowest_fraction = 1.0 - highest_fraction;
440 CLAMP(highest_fraction, 0, 1);
441 CLAMP(lowest_fraction, 0, 1);
443 // printf("InterpolateVideo::process_buffer %lld %lld %lld %f %f %lld %lld %f %f\n",
446 // requested_range_start,
447 // requested_range_end,
449 // config.input_rate,
452 // highest_fraction);
454 int w = frame->get_w();
455 int h = frame->get_h();
456 switch(frame->get_color_model())
459 AVERAGE(float, float, 3, 1);
463 AVERAGE(unsigned char, int, 3, 0xff);
466 AVERAGE(float, float, 4, 1);
470 AVERAGE(unsigned char, int, 4, 0xff);
474 AVERAGE(uint16_t, int, 3, 0xffff);
476 case BC_RGBA16161616:
477 case BC_YUVA16161616:
478 AVERAGE(uint16_t, int, 4, 0xffff);
487 int InterpolateVideo::is_realtime()
492 char* InterpolateVideo::plugin_title()
494 return N_("Interpolate");
497 NEW_PICON_MACRO(InterpolateVideo)
499 SHOW_GUI_MACRO(InterpolateVideo, InterpolateVideoThread)
501 RAISE_WINDOW_MACRO(InterpolateVideo)
503 SET_STRING_MACRO(InterpolateVideo)
505 int InterpolateVideo::load_configuration()
507 KeyFrame *prev_keyframe, *next_keyframe;
508 InterpolateVideoConfig old_config;
509 old_config.copy_from(&config);
511 next_keyframe = get_next_keyframe(get_source_position());
512 prev_keyframe = get_prev_keyframe(get_source_position());
513 // Previous keyframe stays in config object.
514 read_data(prev_keyframe);
517 int64_t prev_position = edl_to_local(prev_keyframe->position);
518 int64_t next_position = edl_to_local(next_keyframe->position);
519 if(prev_position == 0 && next_position == 0)
521 next_position = prev_position = get_source_start();
523 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld\n",
524 // prev_keyframe->position,
525 // next_keyframe->position,
529 // Get range to average in requested rate
530 range_start = prev_position;
531 range_end = next_position;
534 // Use keyframes to determine range
535 if(config.use_keyframes)
537 // Between keyframe and edge of range or no keyframes
538 if(range_start == range_end)
540 // Between first keyframe and start of effect
541 if(get_source_position() >= get_source_start() &&
542 get_source_position() < range_start)
544 range_start = get_source_start();
547 // Between last keyframe and end of effect
548 if(get_source_position() >= range_start &&
549 get_source_position() < get_source_start() + get_total_len())
551 // Last frame should be inclusive of current effect
552 range_end = get_source_start() + get_total_len() - 1;
556 // Should never get here
561 // Convert requested rate to input rate
562 range_start = (int64_t)((double)range_start / get_framerate() * config.input_rate + 0.5);
563 range_end = (int64_t)((double)range_end / get_framerate() * config.input_rate + 0.5);
568 // Convert to input frame rate
569 range_start = (int64_t)(get_source_position() /
572 range_end = (int64_t)(get_source_position() /
574 config.input_rate) + 1;
577 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld %lld %lld\n",
578 // prev_keyframe->position,
579 // next_keyframe->position,
586 return !config.equivalent(&old_config);
589 int InterpolateVideo::load_defaults()
591 char directory[BCTEXTLEN];
592 // set the default directory
593 sprintf(directory, "%sinterpolatevideo.rc", BCASTDIR);
596 defaults = new Defaults(directory);
599 config.input_rate = defaults->get("INPUT_RATE", config.input_rate);
600 config.input_rate = Units::fix_framerate(config.input_rate);
601 config.use_keyframes = defaults->get("USE_KEYFRAMES", config.use_keyframes);
605 int InterpolateVideo::save_defaults()
607 defaults->update("INPUT_RATE", config.input_rate);
608 defaults->update("USE_KEYFRAMES", config.use_keyframes);
613 void InterpolateVideo::save_data(KeyFrame *keyframe)
617 // cause data to be stored directly in text
618 output.set_shared_string(keyframe->data, MESSAGESIZE);
619 output.tag.set_title("INTERPOLATEVIDEO");
620 output.tag.set_property("INPUT_RATE", config.input_rate);
621 output.tag.set_property("USE_KEYFRAMES", config.use_keyframes);
623 output.terminate_string();
626 void InterpolateVideo::read_data(KeyFrame *keyframe)
630 input.set_shared_string(keyframe->data, strlen(keyframe->data));
634 while(!input.read_tag())
636 if(input.tag.title_is("INTERPOLATEVIDEO"))
638 config.input_rate = input.tag.get_property("INPUT_RATE", config.input_rate);
639 config.input_rate = Units::fix_framerate(config.input_rate);
640 config.use_keyframes = input.tag.get_property("USE_KEYFRAMES", config.use_keyframes);
645 void InterpolateVideo::update_gui()
649 if(load_configuration())
651 thread->window->lock_window("InterpolateVideo::update_gui");
652 thread->window->rate->update((float)config.input_rate);
653 thread->window->keyframes->update(config.use_keyframes);
654 thread->window->unlock_window();