r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / plugins / 1080to480 / 1080to480.C
blob750699e07e947e3622ea755103593b51582915bd
1 #include "1080to480.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "bcdisplayinfo.h"
6 #include "keyframe.h"
7 #include "overlayframe.h"
8 #include "picon_png.h"
9 #include "vframe.h"
13 #include <libintl.h>
14 #define _(String) gettext(String)
15 #define gettext_noop(String) String
16 #define N_(String) gettext_noop (String)
22 #include <stdint.h>
23 #include <string.h>
26 REGISTER_PLUGIN(_1080to480Main)
31 _1080to480Config::_1080to480Config()
33         first_field = 0;
36 int _1080to480Config::equivalent(_1080to480Config &that)
38         return first_field == that.first_field;
41 void _1080to480Config::copy_from(_1080to480Config &that)
43         first_field = that.first_field;
46 void _1080to480Config::interpolate(_1080to480Config &prev, 
47         _1080to480Config &next, 
48         long prev_frame, 
49         long next_frame, 
50         long current_frame)
52         copy_from(prev);
59 _1080to480Window::_1080to480Window(_1080to480Main *client, int x, int y)
60  : BC_Window(client->gui_string, 
61         x, 
62         y, 
63         200, 
64         100, 
65         200, 
66         100, 
67         0, 
68         0,
69         1)
70
71         this->client = client; 
75 _1080to480Window::~_1080to480Window()
79 int _1080to480Window::create_objects()
81         int x = 10, y = 10;
83         add_tool(odd_first = new _1080to480Option(client, this, 1, x, y, _("Odd field first")));
84         y += 25;
85         add_tool(even_first = new _1080to480Option(client, this, 0, x, y, _("Even field first")));
87         show_window();
88         flush();
89         return 0;
92 WINDOW_CLOSE_EVENT(_1080to480Window)
94 int _1080to480Window::set_first_field(int first_field, int send_event)
96         odd_first->update(first_field == 1);
97         even_first->update(first_field == 0);
100         if(send_event)
101         {
102                 client->config.first_field = first_field;
103                 client->send_configure_change();
104         }
105         return 0;
111 _1080to480Option::_1080to480Option(_1080to480Main *client, 
112                 _1080to480Window *window, 
113                 int output, 
114                 int x, 
115                 int y, 
116                 char *text)
117  : BC_Radial(x, 
118         y, 
119         client->config.first_field == output, 
120         text)
122         this->client = client;
123         this->window = window;
124         this->output = output;
127 int _1080to480Option::handle_event()
129         window->set_first_field(output, 1);
130         return 1;
135 PLUGIN_THREAD_OBJECT(_1080to480Main, _1080to480Thread, _1080to480Window)
143 _1080to480Main::_1080to480Main(PluginServer *server)
144  : PluginVClient(server)
146         PLUGIN_CONSTRUCTOR_MACRO
147         temp = 0;
150 _1080to480Main::~_1080to480Main()
152         PLUGIN_DESTRUCTOR_MACRO
153         if(temp) delete temp;
156 char* _1080to480Main::plugin_title() { return _("1080 to 480"); }
157 int _1080to480Main::is_realtime() { return 1; }
159 SHOW_GUI_MACRO(_1080to480Main, _1080to480Thread)
160 RAISE_WINDOW_MACRO(_1080to480Main)
161 SET_STRING_MACRO(_1080to480Main)
162 NEW_PICON_MACRO(_1080to480Main)
163 LOAD_CONFIGURATION_MACRO(_1080to480Main, _1080to480Config)
166 #define TEMP_W 854
167 #define TEMP_H 480
168 #define OUT_ROWS 240
170 void _1080to480Main::reduce_field(VFrame *output, VFrame *input, int src_field, int dst_field)
172         int w = input->get_w();
173         int h = input->get_h();
175         if(h > output->get_h()) h = output->get_h();
176         if(w > output->get_w()) h = output->get_w();
178 #define REDUCE_MACRO(type, components) \
179 for(int i = 0; i < OUT_ROWS; i++) \
180 { \
181         int in_number1 = dst_field * 2 + src_field + (int)(i * 9 / 4) * 2; \
182         int in_number2 = in_number1 + 2; \
183         int in_number3 = in_number2 + 2; \
184         int in_number4 = in_number3 + 2; \
185         int out_number = dst_field + i * 2; \
187         if(in_number1 >= h) in_number1 = h - 1; \
188         if(in_number2 >= h) in_number2 = h - 1; \
189         if(in_number3 >= h) in_number3 = h - 1; \
190         if(in_number4 >= h) in_number4 = h - 1; \
191         if(out_number >= h) out_number = h - 1; \
193         type *in_row1 = (type*)input->get_rows()[in_number1]; \
194         type *in_row2 = (type*)input->get_rows()[in_number2]; \
195         type *in_row3 = (type*)input->get_rows()[in_number3]; \
196         type *in_row4 = (type*)input->get_rows()[in_number4]; \
197         type *out_row = (type*)output->get_rows()[out_number]; \
199         for(int j = 0; j < w * components; j++) \
200         { \
201                 *out_row++ = ((int64_t)*in_row1++ +  \
202                         (int64_t)*in_row2++ +  \
203                         (int64_t)*in_row3++ +  \
204                         (int64_t)*in_row4++) >> 2; \
205         } \
208         switch(input->get_color_model())
209         {
210                 case BC_RGB888:
211                 case BC_YUV888:
212                         REDUCE_MACRO(unsigned char, 3);
213                         break;
214                 case BC_RGBA8888:
215                 case BC_YUVA8888:
216                         REDUCE_MACRO(unsigned char, 4);
217                         break;
218                 case BC_RGB161616:
219                 case BC_YUV161616:
220                         REDUCE_MACRO(uint16_t, 3);
221                         break;
222                 case BC_RGBA16161616:
223                 case BC_YUVA16161616:
224                         REDUCE_MACRO(uint16_t, 4);
225                         break;
226         }
230 int _1080to480Main::process_realtime(VFrame *input, VFrame *output)
232         load_configuration();
233         if(!temp)
234         {
235                 temp = new VFrame(0,
236                         input->get_w(),
237                         input->get_h(),
238                         input->get_color_model());
239                 temp->clear_frame();
240         }
242         reduce_field(temp, input, config.first_field == 0 ? 0 : 1, 0);
243         reduce_field(temp, input, config.first_field == 0 ? 1 : 0, 1);
244         
245         output->copy_from(temp);
247         return 0;
251 int _1080to480Main::load_defaults()
253         char directory[BCTEXTLEN], string[BCTEXTLEN];
254         sprintf(directory, "%s1080to480.rc", BCASTDIR);
255         
256         defaults = new Defaults(directory);
257         defaults->load();
258         config.first_field = defaults->get("FIRST_FIELD", config.first_field);
259         return 0;
263 int _1080to480Main::save_defaults()
265         defaults->update("FIRST_FIELD", config.first_field);
266         defaults->save();
267         return 0;
270 void _1080to480Main::save_data(KeyFrame *keyframe)
272         FileXML output;
273         output.set_shared_string(keyframe->data, MESSAGESIZE);
274         output.tag.set_title("1080TO480");
275         output.tag.set_property("FIRST_FIELD", config.first_field);
276         output.append_tag();
277         output.terminate_string();
280 void _1080to480Main::read_data(KeyFrame *keyframe)
282         FileXML input;
283         input.set_shared_string(keyframe->data, strlen(keyframe->data));
285         while(!input.read_tag())
286         {
287                 if(input.tag.title_is("1080TO480"))
288                 {
289                         config.first_field = input.tag.get_property("FIRST_FIELD", config.first_field);
290                 }
291         }
294 void _1080to480Main::update_gui()
296         if(thread) 
297         {
298                 load_configuration();
299                 thread->window->lock_window();
300                 thread->window->set_first_field(config.first_field, 0);
301                 thread->window->unlock_window();
302         }