Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / 720to480 / 720to480.C
blob19bff351ea23e5d1d464b6008e437c29e5edbdfd
1 #include "720to480.h"
2 #include "clip.h"
3 #include "bchash.h"
4 #include "filexml.h"
5 #include "bcdisplayinfo.h"
6 #include "keyframe.h"
7 #include "language.h"
8 #include "mainprogress.h"
9 #include "vframe.h"
12 #include <stdint.h>
13 #include <string.h>
16 REGISTER_PLUGIN(_720to480Main)
19 #define FORWARD 0
20 #define REVERSE 1
22 _720to480Config::_720to480Config()
24         first_field = 0;
25         direction = FORWARD;
32 _720to480Window::_720to480Window(_720to480Main *client, int x, int y)
33  : BC_Window(client->gui_string, 
34         x, 
35         y, 
36         230, 
37         150, 
38         230, 
39         150, 
40         0, 
41         0,
42         1)
43
44         this->client = client; 
48 _720to480Window::~_720to480Window()
52 int _720to480Window::create_objects()
54         int x = 10, y = 10;
56         add_tool(odd_first = new _720to480Order(client, this, 1, x, y, _("Odd field first")));
57         y += 25;
58         add_tool(even_first = new _720to480Order(client, this, 0, x, y, _("Even field first")));
60 //      y += 25;
61 //      add_tool(forward = new _720to480Direction(client, this, FORWARD, x, y, _("Downsample")));
62 //      y += 25;
63 //      add_tool(reverse = new _720to480Direction(client, this, REVERSE, x, y, _("Upsample")));
64 // 
65         add_subwindow(new BC_OKButton(this));
66         add_subwindow(new BC_CancelButton(this));
68         show_window();
69         flush();
70         return 0;
73 WINDOW_CLOSE_EVENT(_720to480Window)
75 int _720to480Window::set_first_field(int first_field)
77         odd_first->update(first_field == 1);
78         even_first->update(first_field == 0);
80         client->config.first_field = first_field;
81         return 0;
84 int _720to480Window::set_direction(int direction)
86         forward->update(direction == FORWARD);
87         reverse->update(direction == REVERSE);
90         client->config.direction = direction;
91         return 0;
96 _720to480Order::_720to480Order(_720to480Main *client, 
97                 _720to480Window *window, 
98                 int output, 
99                 int x, 
100                 int y, 
101                 char *text)
102  : BC_Radial(x, 
103         y, 
104         client->config.first_field == output, 
105         text)
107         this->client = client;
108         this->window = window;
109         this->output = output;
112 int _720to480Order::handle_event()
114         window->set_first_field(output);
115         return 1;
122 _720to480Direction::_720to480Direction(_720to480Main *client, 
123                 _720to480Window *window, 
124                 int output, 
125                 int x, 
126                 int y, 
127                 char *text)
128  : BC_Radial(x, 
129         y, 
130         client->config.direction == output, 
131         text)
133         this->client = client;
134         this->window = window;
135         this->output = output;
138 int _720to480Direction::handle_event()
140         window->set_direction(output);
141         return 1;
159 _720to480Main::_720to480Main(PluginServer *server)
160  : PluginVClient(server)
162         temp = 0;
163         load_defaults();
166 _720to480Main::~_720to480Main()
168         save_defaults();
169         delete defaults;
171         if(temp) delete temp;
174 char* _720to480Main::plugin_title() { return N_("720 to 480"); }
175 int _720to480Main::is_realtime() { return 0; }
177 double _720to480Main::get_framerate()
179         return project_frame_rate / 2;
186 int _720to480Main::load_defaults()
188         char directory[BCTEXTLEN], string[BCTEXTLEN];
189         sprintf(directory, "%s720to480.rc", BCASTDIR);
190         
191         defaults = new BC_Hash(directory);
192         defaults->load();
193         config.first_field = defaults->get("FIRST_FIELD", config.first_field);
194         config.direction = defaults->get("DIRECTION", config.direction);
195         return 0;
199 int _720to480Main::save_defaults()
201         defaults->update("FIRST_FIELD", config.first_field);
202         defaults->update("DIRECTION", config.direction);
203         defaults->save();
204         return 0;
207 int _720to480Main::get_parameters()
209         BC_DisplayInfo info;
210         _720to480Window window(this, 
211                 info.get_abs_cursor_x(), 
212                 info.get_abs_cursor_y());
213         window.create_objects();
214         int result = window.run_window();
215         return result;
218 int _720to480Main::start_loop()
220         if(PluginClient::interactive)
221         {
222                 char string[BCTEXTLEN];
223                 sprintf(string, "%s...", plugin_title());
224                 progress = start_progress(string, 
225                         PluginClient::end - PluginClient::start);
226         }
228         input_position = PluginClient::start;
229         return 0;
233 int _720to480Main::stop_loop()
235         if(PluginClient::interactive)
236         {
237                 progress->stop_progress();
238                 delete progress;
239         }
240         return 0;
244 #define DST_W 854
245 #define DST_H 240
248 void _720to480Main::reduce_field(VFrame *output, VFrame *input, int dest_row)
250         int in_w = input->get_w();
251         int in_h = input->get_h();
252         int out_w = output->get_w();
253         int out_h = output->get_h();
255 #define REDUCE_MACRO(type, temp, components) \
256 for(int i = 0; i < DST_H; i++) \
257 { \
258         int output_number = dest_row + i * 2; \
259         if(output_number >= out_h) break; \
261         int in1 = i * 3 + dest_row * 2; \
262         int in2 = i * 3 + 1 + dest_row * 2; \
263         int in3 = i * 3 + 2 + dest_row * 2; \
265         if(in1 >= in_h) in1 = in_h - 1; \
266         if(in2 >= in_h) in2 = in_h - 1; \
267         if(in3 >= in_h) in3 = in_h - 1; \
269         type *out_row = (type*)output->get_rows()[output_number]; \
270         type *in_row1 = (type*)input->get_rows()[in1]; \
271         type *in_row2 = (type*)input->get_rows()[in2]; \
272         type *in_row3 = (type*)input->get_rows()[in3]; \
274         int w = MIN(out_w, in_w) * components; \
275         for(int j = 0; j < w; j++) \
276         { \
277                 *out_row++ = ((temp)*in_row1++ + \
278                         (temp)*in_row2++ + \
279                         (temp)*in_row3++) / 3; \
280         } \
283         switch(input->get_color_model())
284         {
285                 case BC_RGB888:
286                 case BC_YUV888:
287                         REDUCE_MACRO(unsigned char, int64_t, 3);
288                         break;
289                 case BC_RGB_FLOAT:
290                         REDUCE_MACRO(float, float, 3);
291                         break;
292                 case BC_RGBA8888:
293                 case BC_YUVA8888:
294                         REDUCE_MACRO(unsigned char, int64_t, 4);
295                         break;
296                 case BC_RGBA_FLOAT:
297                         REDUCE_MACRO(float, float, 4);
298                         break;
299                 case BC_RGB161616:
300                 case BC_YUV161616:
301                         REDUCE_MACRO(uint16_t, int64_t, 3);
302                         break;
303                 case BC_RGBA16161616:
304                 case BC_YUVA16161616:
305                         REDUCE_MACRO(uint16_t, int64_t, 4);
306                         break;
307         }
310 int _720to480Main::process_loop(VFrame *output)
312         int result = 0;
314         if(!temp)
315                 temp = new VFrame(0,
316                         output->get_w(),
317                         output->get_h(),
318                         output->get_color_model());
320         if(config.direction == FORWARD)
321         {
322 // Step 1: Reduce vertically and put in desired fields of output
323                 read_frame(temp, input_position);
324                 reduce_field(output, temp, config.first_field == 0 ? 0 : 1);
325                 input_position++;
327                 read_frame(temp, input_position);
328                 reduce_field(output, temp, config.first_field == 0 ? 1 : 0);
329                 input_position++;
330         }
332         if(PluginClient::interactive) 
333                 result = progress->update(input_position - PluginClient::start);
335         if(input_position >= PluginClient::end) result = 1;
337         return result;
345 void _720to480Main::save_data(KeyFrame *keyframe)
347         FileXML output;
348         output.set_shared_string(keyframe->data, MESSAGESIZE);
349         output.tag.set_title("720TO480");
350         output.tag.set_property("FIRST_FIELD", config.first_field);
351         output.tag.set_property("DIRECTION", config.direction);
352         output.append_tag();
353         output.terminate_string();
356 void _720to480Main::read_data(KeyFrame *keyframe)
358         FileXML input;
359         input.set_shared_string(keyframe->data, strlen(keyframe->data));
361         while(!input.read_tag())
362         {
363                 if(input.tag.title_is("720TO480"))
364                 {
365                         config.first_field = input.tag.get_property("FIRST_FIELD", config.first_field);
366                         config.direction = input.tag.get_property("DIRECTION", config.direction);
367                 }
368         }