r665: Merged the official release 2.0.
[cinelerra_cv.git] / plugins / fieldframe / fieldframe.C
blob744761e0212a5d15ce2af6d5e9146bb371e31701
1 #include "bcdisplayinfo.h"
2 #include "defaults.h"
3 #include "filexml.h"
4 #include "guicast.h"
5 #include "keyframe.h"
6 #include "transportque.h"
7 #include "language.h"
8 #include "mainprogress.h"
9 #include "picon_png.h"
10 #include "pluginvclient.h"
11 #include "transportque.inc"
12 #include "vframe.h"
14 #include <string.h>
17 #define TOP_FIELD_FIRST 0
18 #define BOTTOM_FIELD_FIRST 1
20 class FieldFrame;
21 class FieldFrameWindow;
29 class FieldFrameConfig
31 public:
32         FieldFrameConfig();
33         int equivalent(FieldFrameConfig &src);
34         int field_dominance;
35         int first_frame;
41 class FieldFrameTop : public BC_Radial
43 public:
44         FieldFrameTop(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
45         int handle_event();
46         FieldFrame *plugin;
47         FieldFrameWindow *gui;
51 class FieldFrameBottom : public BC_Radial
53 public:
54         FieldFrameBottom(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
55         int handle_event();
56         FieldFrame *plugin;
57         FieldFrameWindow *gui;
60 // class FieldFrameFirst : public BC_Radial
61 // {
62 // public:
63 //      FieldFrameFirst(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
64 //      int handle_event();
65 //      FieldFrame *plugin;
66 //      FieldFrameWindow *gui;
67 // };
68 // 
69 // class FieldFrameSecond : public BC_Radial
70 // {
71 // public:
72 //      FieldFrameSecond(FieldFrame *plugin, FieldFrameWindow *gui, int x, int y);
73 //      int handle_event();
74 //      FieldFrame *plugin;
75 //      FieldFrameWindow *gui;
76 // };
78 class FieldFrameWindow : public BC_Window
80 public:
81         FieldFrameWindow(FieldFrame *plugin, int x, int y);
82         void create_objects();
83         int close_event();
84         FieldFrame *plugin;
85         FieldFrameTop *top;
86         FieldFrameBottom *bottom;
87 //      FieldFrameFirst *first;
88 //      FieldFrameSecond *second;
92 PLUGIN_THREAD_HEADER(FieldFrame, FieldFrameThread, FieldFrameWindow)
95 class FieldFrame : public PluginVClient
97 public:
98         FieldFrame(PluginServer *server);
99         ~FieldFrame();
101         PLUGIN_CLASS_MEMBERS(FieldFrameConfig, FieldFrameThread);
103         int process_buffer(VFrame *frame,
104                 int64_t start_position,
105                 double frame_rate);
106         int is_realtime();
107         int load_defaults();
108         int save_defaults();
109         void save_data(KeyFrame *keyframe);
110         void read_data(KeyFrame *keyframe);
111         void update_gui();
112         void apply_field(VFrame *output, VFrame *input, int field);
115         VFrame *input;
125 REGISTER_PLUGIN(FieldFrame)
130 FieldFrameConfig::FieldFrameConfig()
132         field_dominance = TOP_FIELD_FIRST;
133         first_frame = 0;
136 int FieldFrameConfig::equivalent(FieldFrameConfig &src)
138         return src.field_dominance == field_dominance &&
139                 src.first_frame == first_frame;
149 FieldFrameWindow::FieldFrameWindow(FieldFrame *plugin, int x, int y)
150  : BC_Window(plugin->gui_string, 
151         x, 
152         y, 
153         230, 
154         100, 
155         230, 
156         100, 
157         0, 
158         0,
159         1)
161         this->plugin = plugin;
164 void FieldFrameWindow::create_objects()
166         int x = 10, y = 10;
167         add_subwindow(top = new FieldFrameTop(plugin, this, x, y));
168         y += 30;
169         add_subwindow(bottom = new FieldFrameBottom(plugin, this, x, y));
170 //      y += 30;
171 //      add_subwindow(first = new FieldFrameFirst(plugin, this, x, y));
172 //      y += 30;
173 //      add_subwindow(second = new FieldFrameSecond(plugin, this, x, y));
175         show_window();
176         flush();
179 WINDOW_CLOSE_EVENT(FieldFrameWindow)
193 FieldFrameTop::FieldFrameTop(FieldFrame *plugin, 
194         FieldFrameWindow *gui, 
195         int x, 
196         int y)
197  : BC_Radial(x, 
198         y, 
199         plugin->config.field_dominance == TOP_FIELD_FIRST,
200         _("Top field first"))
202         this->plugin = plugin;
203         this->gui = gui;
206 int FieldFrameTop::handle_event()
208         plugin->config.field_dominance = TOP_FIELD_FIRST;
209         gui->bottom->update(0);
210         plugin->send_configure_change();
211         return 1;
218 FieldFrameBottom::FieldFrameBottom(FieldFrame *plugin, 
219         FieldFrameWindow *gui, 
220         int x, 
221         int y)
222  : BC_Radial(x, 
223         y, 
224         plugin->config.field_dominance == BOTTOM_FIELD_FIRST,
225         _("Bottom field first"))
227         this->plugin = plugin;
228         this->gui = gui;
231 int FieldFrameBottom::handle_event()
233         plugin->config.field_dominance = BOTTOM_FIELD_FIRST;
234         gui->top->update(0);
235         plugin->send_configure_change();
236         return 1;
243 // FieldFrameFirst::FieldFrameFirst(FieldFrame *plugin, 
244 //      FieldFrameWindow *gui, 
245 //      int x, 
246 //      int y)
247 //  : BC_Radial(x, 
248 //      y, 
249 //      plugin->config.first_frame == 0,
250 //      _("First frame is first field"))
251 // {
252 //      this->plugin = plugin;
253 //      this->gui = gui;
254 // }
255 // 
256 // int FieldFrameFirst::handle_event()
257 // {
258 //      plugin->config.first_frame = 0;
259 //      gui->second->update(0);
260 //      plugin->send_configure_change();
261 //      return 1;
262 // }
263 // 
264 // 
265 // 
266 // 
267 // FieldFrameSecond::FieldFrameSecond(FieldFrame *plugin, 
268 //      FieldFrameWindow *gui, 
269 //      int x, 
270 //      int y)
271 //  : BC_Radial(x, 
272 //      y, 
273 //      plugin->config.first_frame == 1,
274 //      _("Second frame is first field"))
275 // {
276 //      this->plugin = plugin;
277 //      this->gui = gui;
278 // }
279 // 
280 // int FieldFrameSecond::handle_event()
281 // {
282 //      plugin->config.first_frame = 1;
283 //      gui->first->update(0);
284 //      plugin->send_configure_change();
285 //      return 1;
286 // }
303 PLUGIN_THREAD_OBJECT(FieldFrame, FieldFrameThread, FieldFrameWindow)
309 FieldFrame::FieldFrame(PluginServer *server)
310  : PluginVClient(server)
312         PLUGIN_CONSTRUCTOR_MACRO
313         input = 0;
317 FieldFrame::~FieldFrame()
319         PLUGIN_DESTRUCTOR_MACRO
321         if(input) delete input;
324 char* FieldFrame::plugin_title() { return N_("Fields to frames"); }
325 int FieldFrame::is_realtime() { return 1; }
328 NEW_PICON_MACRO(FieldFrame)
330 SHOW_GUI_MACRO(FieldFrame, FieldFrameThread)
332 RAISE_WINDOW_MACRO(FieldFrame)
334 SET_STRING_MACRO(FieldFrame);
336 int FieldFrame::load_configuration()
338         KeyFrame *prev_keyframe;
339         FieldFrameConfig old_config = config;
341         prev_keyframe = get_prev_keyframe(get_source_position());
342         read_data(prev_keyframe);
344         return !old_config.equivalent(config);
348 int FieldFrame::load_defaults()
350         char directory[BCTEXTLEN];
351 // set the default directory
352         sprintf(directory, "%sfieldframe.rc", BCASTDIR);
354 // load the defaults
355         defaults = new Defaults(directory);
356         defaults->load();
358         config.field_dominance = defaults->get("DOMINANCE", config.field_dominance);
359         config.first_frame = defaults->get("FIRST_FRAME", config.first_frame);
360         return 0;
363 int FieldFrame::save_defaults()
365         defaults->update("DOMINANCE", config.field_dominance);
366         defaults->update("FIRST_FRAME", config.first_frame);
367         defaults->save();
368         return 0;
371 void FieldFrame::save_data(KeyFrame *keyframe)
373         FileXML output;
375 // cause data to be stored directly in text
376         output.set_shared_string(keyframe->data, MESSAGESIZE);
377         output.tag.set_title("FIELD_FRAME");
378         output.tag.set_property("DOMINANCE", config.field_dominance);
379         output.tag.set_property("FIRST_FRAME", config.first_frame);
380         output.append_tag();
381         output.terminate_string();
384 void FieldFrame::read_data(KeyFrame *keyframe)
386         FileXML input;
388         input.set_shared_string(keyframe->data, strlen(keyframe->data));
390         int result = 0;
392         while(!input.read_tag())
393         {
394                 if(input.tag.title_is("FIELD_FRAME"))
395                 {
396                         config.field_dominance = input.tag.get_property("DOMINANCE", config.field_dominance);
397                         config.first_frame = input.tag.get_property("FIRST_FRAME", config.first_frame);
398                 }
399         }
403 void FieldFrame::update_gui()
405         if(thread)
406         {
407                 if(load_configuration())
408                 {
409                         thread->window->lock_window();
410                         thread->window->top->update(config.field_dominance == TOP_FIELD_FIRST);
411                         thread->window->bottom->update(config.field_dominance == BOTTOM_FIELD_FIRST);
412 //                      thread->window->first->update(config.first_frame == 0);
413 //                      thread->window->second->update(config.first_frame == 1);
414                         thread->window->unlock_window();
415                 }
416         }
420 int FieldFrame::process_buffer(VFrame *frame,
421                 int64_t start_position,
422                 double frame_rate)
424         int result = 0;
425         load_configuration();
427         if(input && !input->equivalent(frame))
428         {
429                 delete input;
430                 input = 0;
431         }
433         if(!input)
434         {
435                 input = new VFrame(0, 
436                         frame->get_w(), 
437                         frame->get_h(), 
438                         frame->get_color_model());
439         }
441 // Get input frames
442         int64_t field1_position = start_position * 2;
443         int64_t field2_position = start_position * 2 + 1;
445         if (get_direction() == PLAY_REVERSE)
446         {
447                 field1_position -= 1;
448                 field2_position -= 1;
449         }
452 // printf("FieldFrame::process_buffer %d %lld %lld\n", 
453 // config.field_dominance, 
454 // field1_position, 
455 // field2_position);
456         read_frame(input, 
457                 0, 
458                 field1_position,
459                 frame_rate * 2);
460         apply_field(frame, 
461                 input, 
462                 config.field_dominance == TOP_FIELD_FIRST ? 0 : 1);
463         read_frame(input, 
464                 0, 
465                 field2_position,
466                 frame_rate * 2);
467         apply_field(frame, 
468                 input, 
469                 config.field_dominance == TOP_FIELD_FIRST ? 1 : 0);
475         return result;
479 void FieldFrame::apply_field(VFrame *output, VFrame *input, int field)
481         unsigned char **input_rows = input->get_rows();
482         unsigned char **output_rows = output->get_rows();
483         int row_size = VFrame::calculate_bytes_per_pixel(output->get_color_model()) * output->get_w();
484         for(int i = field; i < output->get_h(); i += 2)
485         {
486                 memcpy(output_rows[i], input_rows[i], row_size);
487         }