r705: More gettextizations (mostly plugins) by Jean-Luc Coulon.
[cinelerra_cv.git] / plugins / interpolatevideo / interpolatevideo.C
blob92560fd3438c089936c215c58da824ec77d06360
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "keyframe.h"
7 #include "language.h"
8 #include "picon_png.h"
9 #include "pluginvclient.h"
10 #include "theme.h"
11 #include "transportque.inc"
12 #include "vframe.h"
14 #include <string.h>
15 #include <stdint.h>
19 class InterpolateVideo;
20 class InterpolateVideoWindow;
23 class InterpolateVideoConfig
25 public:
26         InterpolateVideoConfig();
28         void copy_from(InterpolateVideoConfig *config);
29         int equivalent(InterpolateVideoConfig *config);
31 // Frame rate of input
32         double input_rate;
33 // If 1, use the keyframes as beginning and end frames and ignore input rate
34         int use_keyframes;
40 class InterpolateVideoRate : public BC_TextBox
42 public:
43         InterpolateVideoRate(InterpolateVideo *plugin, 
44                 InterpolateVideoWindow *gui, 
45                 int x, 
46                 int y);
47         int handle_event();
48         InterpolateVideo *plugin;
49         InterpolateVideoWindow *gui;
52 class InterpolateVideoRateMenu : public BC_ListBox
54 public:
55         InterpolateVideoRateMenu(InterpolateVideo *plugin, 
56                 InterpolateVideoWindow *gui, 
57                 int x, 
58                 int y);
59         int handle_event();
60         InterpolateVideo *plugin;
61         InterpolateVideoWindow *gui;
64 class InterpolateVideoKeyframes : public BC_CheckBox
66 public:
67         InterpolateVideoKeyframes(InterpolateVideo *plugin,
68                 InterpolateVideoWindow *gui,
69                 int x, 
70                 int y);
71         int handle_event();
72         InterpolateVideoWindow *gui;
73         InterpolateVideo *plugin;
76 class InterpolateVideoWindow : public BC_Window
78 public:
79         InterpolateVideoWindow(InterpolateVideo *plugin, int x, int y);
80         ~InterpolateVideoWindow();
82         void create_objects();
83         int close_event();
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
101 public:
102         InterpolateVideo(PluginServer *server);
103         ~InterpolateVideo();
105         PLUGIN_CLASS_MEMBERS(InterpolateVideoConfig, InterpolateVideoThread)
107         int process_buffer(VFrame *frame,
108                 int64_t start_position,
109                 double frame_rate);
110         int is_realtime();
111         int load_defaults();
112         int save_defaults();
113         void save_data(KeyFrame *keyframe);
114         void read_data(KeyFrame *keyframe);
115         void update_gui();
117         void fill_border(double frame_rate, int64_t start_position);
119 // beginning and end frames
120         VFrame *frames[2];
121 // Last requested positions
122         int64_t frame_number[2];
123 // Last output position
124         int64_t last_position;
125         double last_rate;
127 // Current requested positions
128         int64_t range_start;
129         int64_t range_end;
131 // Input rate determined by keyframe mode
132         double active_input_rate;
146 InterpolateVideoConfig::InterpolateVideoConfig()
148         input_rate = (double)30000 / 1001;
149         use_keyframes = 0;
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, 
174         x, 
175         y, 
176         210, 
177         160, 
178         200, 
179         160, 
180         0, 
181         0,
182         1)
184         this->plugin = plugin;
187 InterpolateVideoWindow::~InterpolateVideoWindow()
191 void InterpolateVideoWindow::create_objects()
193         int x = 10, y = 10;
195         BC_Title *title;
196         add_subwindow(title = new BC_Title(x, y, _("Input frames per second:")));
197         y += 30;
198         add_subwindow(rate = new InterpolateVideoRate(plugin, 
199                 this, 
200                 x, 
201                 y));
202         add_subwindow(rate_menu = new InterpolateVideoRateMenu(plugin, 
203                 this, 
204                 x + rate->get_w() + 5, 
205                 y));
206         y += 30;
207         add_subwindow(keyframes = new InterpolateVideoKeyframes(plugin,
208                 this,
209                 x, 
210                 y));
212         update_enabled();
213         show_window();
214         flush();
217 void InterpolateVideoWindow::update_enabled()
219         if(plugin->config.use_keyframes)
220         {
221                 rate->disable();
222         }
223         else
224         {
225                 rate->enable();
226         }
229 WINDOW_CLOSE_EVENT(InterpolateVideoWindow)
242 InterpolateVideoRate::InterpolateVideoRate(InterpolateVideo *plugin, 
243         InterpolateVideoWindow *gui, 
244         int x, 
245         int y)
246  : BC_TextBox(x, 
247         y, 
248         90,
249         1,
250         (float)plugin->config.input_rate)
252         this->plugin = plugin;
253         this->gui = gui;
256 int InterpolateVideoRate::handle_event()
258         plugin->config.input_rate = Units::atoframerate(get_text());
259         plugin->send_configure_change();
260         return 1;
266 InterpolateVideoRateMenu::InterpolateVideoRateMenu(InterpolateVideo *plugin, 
267         InterpolateVideoWindow *gui, 
268         int x, 
269         int y)
270  : BC_ListBox(x,
271         y,
272         100,
273         200,
274         LISTBOX_TEXT,
275         &plugin->get_theme()->frame_rates,
276         0,
277         0,
278         1,
279         0,
280         1)
282         this->plugin = plugin;
283         this->gui = gui;
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();
292         return 1;
298 InterpolateVideoKeyframes::InterpolateVideoKeyframes(InterpolateVideo *plugin,
299         InterpolateVideoWindow *gui,
300         int x, 
301         int y)
302  : BC_CheckBox(x, 
303         y, 
304         plugin->config.use_keyframes, 
305         _("Use keyframes as input"))
307         this->plugin = plugin;
308         this->gui = gui;
310 int InterpolateVideoKeyframes::handle_event()
312         plugin->config.use_keyframes = get_value();
313         gui->update_enabled();
314         plugin->send_configure_change();
315         return 1;
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;
351         last_position = -1;
352         last_rate = -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 
367 // start position.
368         if(range_start != frame_number[0] || 
369                 last_position != start_position ||
370                 !EQUIV(last_rate, frame_rate))
371         {
372 //printf("InterpolateVideo::fill_border 1 %lld\n", range_start);
373                 read_frame(frames[0], 
374                         0, 
375                         range_start + (get_direction() == PLAY_REVERSE ? 1 : 0), 
376                         active_input_rate);
377         }
379         if(range_end != frame_number[1] || 
380                 last_position != start_position ||
381                 !EQUIV(last_rate, frame_rate))
382         {
383 //printf("InterpolateVideo::fill_border 2 %lld\n", range_start);
384                 read_frame(frames[1], 
385                         0, 
386                         range_end + (get_direction() == PLAY_REVERSE ? 1 : 0), 
387                         active_input_rate);
388         }
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) \
398 { \
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++) \
403         { \
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++) \
408                 { \
409                         *out_row++ = (*in_row0++ * fraction0 + *in_row1++ * fraction1) / max; \
410                 } \
411         } \
418 int InterpolateVideo::process_buffer(VFrame *frame,
419         int64_t start_position,
420         double frame_rate)
422         if(get_direction() == PLAY_REVERSE) start_position--;
423         load_configuration();
425         if(!frames[0])
426         {
427                 for(int i = 0; i < 2; i++)
428                 {
429                         frames[i] = new VFrame(0,
430                                 frame->get_w(),
431                                 frame->get_h(),
432                                 frame->get_color_model(),
433                                 -1);
434                 }
435         }
436 //printf("InterpolateVideo::process_buffer 1 %lld %lld\n", range_start, range_end);
438         if(range_start == range_end)
439         {
440                 read_frame(frame, 
441                         0, 
442                         range_start, 
443                         active_input_rate);
444                 return 0;
445         }
446         else
447         {
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 * 
454                         frame_rate / 
455                         active_input_rate);
456                 int64_t requested_range_end = (int64_t)((double)range_end * 
457                         frame_rate / 
458                         active_input_rate);
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",
468 // range_start,
469 // range_end,
470 // requested_range_start,
471 // requested_range_end,
472 // start_position,
473 // config.input_rate,
474 // frame_rate,
475 // lowest_fraction,
476 // highest_fraction);
478                 int w = frame->get_w();
479                 int h = frame->get_h();
480                 switch(frame->get_color_model())
481                 {
482                         case BC_RGB_FLOAT:
483                                 AVERAGE(float, float, 3, 1);
484                                 break;
485                         case BC_RGB888:
486                         case BC_YUV888:
487                                 AVERAGE(unsigned char, int, 3, 0xff);
488                                 break;
489                         case BC_RGBA_FLOAT:
490                                 AVERAGE(float, float, 4, 1);
491                                 break;
492                         case BC_RGBA8888:
493                         case BC_YUVA8888:
494                                 AVERAGE(unsigned char, int, 4, 0xff);
495                                 break;
496                         case BC_RGB161616:
497                         case BC_YUV161616:
498                                 AVERAGE(uint16_t, int, 3, 0xffff);
499                                 break;
500                         case BC_RGBA16161616:
501                         case BC_YUVA16161616:
502                                 AVERAGE(uint16_t, int, 4, 0xffff);
503                                 break;
504                 }
505         }
506         return 0;
511 int InterpolateVideo::is_realtime()
513         return 1;
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)
544         {
545                 next_position = prev_position = get_source_start();
546         }
547 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld\n",
548 // prev_keyframe->position,
549 // next_keyframe->position,
550 // prev_position,
551 // next_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)
560         {
561                 active_input_rate = get_framerate();
562 // Between keyframe and edge of range or no keyframes
563                 if(range_start == range_end)
564                 {
565 // Between first keyframe and start of effect
566                         if(get_source_position() >= get_source_start() &&
567                                 get_source_position() < range_start)
568                         {
569                                 range_start = get_source_start();
570                         }
571                         else
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())
575                         {
576 // Last frame should be inclusive of current effect
577                                 range_end = get_source_start() + get_total_len() - 1;
578                         }
579                         else
580                         {
581 // Should never get here
582                                 ;
583                         }
584                 }
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", 
591 // range_start, 
592 // range_end,
593 // get_framerate(),
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);
597         }
598         else
599 // Use frame rate
600         {
601                 active_input_rate = config.input_rate;
602 // Convert to input frame rate
603                 range_start = (int64_t)(get_source_position() / 
604                         get_framerate() *
605                         active_input_rate);
606                 range_end = (int64_t)(get_source_position() / 
607                         get_framerate() *
608                         active_input_rate) + 1;
609         }
611 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld %lld %lld\n",
612 // prev_keyframe->position,
613 // next_keyframe->position,
614 // prev_position,
615 // next_position,
616 // range_start,
617 // range_end);
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);
629 // load the defaults
630         defaults = new Defaults(directory);
631         defaults->load();
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);
636         return 0;
639 int InterpolateVideo::save_defaults()
641         defaults->update("INPUT_RATE", config.input_rate);
642         defaults->update("USE_KEYFRAMES", config.use_keyframes);
643         defaults->save();
644         return 0;
647 void InterpolateVideo::save_data(KeyFrame *keyframe)
649         FileXML output;
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);
656         output.append_tag();
657         output.terminate_string();
660 void InterpolateVideo::read_data(KeyFrame *keyframe)
662         FileXML input;
664         input.set_shared_string(keyframe->data, strlen(keyframe->data));
666         int result = 0;
668         while(!input.read_tag())
669         {
670                 if(input.tag.title_is("INTERPOLATEVIDEO"))
671                 {
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);
675                 }
676         }
679 void InterpolateVideo::update_gui()
681         if(thread)
682         {
683                 if(load_configuration())
684                 {
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();
690                 }
691         }