4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "1080to480.h"
26 #include "bcdisplayinfo.h"
29 #include "overlayframe.h"
41 REGISTER_PLUGIN(_1080to480Main)
46 _1080to480Config::_1080to480Config()
51 int _1080to480Config::equivalent(_1080to480Config &that)
53 return first_field == that.first_field;
56 void _1080to480Config::copy_from(_1080to480Config &that)
58 first_field = that.first_field;
61 void _1080to480Config::interpolate(_1080to480Config &prev,
62 _1080to480Config &next,
74 _1080to480Window::_1080to480Window(_1080to480Main *client)
75 : PluginClientWindow(client, 200, 100, 0, 0, 1)
77 this->client = client;
81 _1080to480Window::~_1080to480Window()
85 void _1080to480Window::create_objects()
89 add_tool(odd_first = new _1080to480Option(client, this, 1, x, y, _("Odd field first")));
91 add_tool(even_first = new _1080to480Option(client, this, 0, x, y, _("Even field first")));
97 int _1080to480Window::set_first_field(int first_field, int send_event)
99 odd_first->update(first_field == 1);
100 even_first->update(first_field == 0);
105 client->config.first_field = first_field;
106 client->send_configure_change();
114 _1080to480Option::_1080to480Option(_1080to480Main *client,
115 _1080to480Window *window,
122 client->config.first_field == output,
125 this->client = client;
126 this->window = window;
127 this->output = output;
130 int _1080to480Option::handle_event()
132 window->set_first_field(output, 1);
145 _1080to480Main::_1080to480Main(PluginServer *server)
146 : PluginVClient(server)
152 _1080to480Main::~_1080to480Main()
155 if(temp) delete temp;
158 const char* _1080to480Main::plugin_title() { return _("1080 to 480"); }
159 int _1080to480Main::is_realtime() { return 1; }
161 NEW_WINDOW_MACRO(_1080to480Main, _1080to480Window)
162 LOAD_CONFIGURATION_MACRO(_1080to480Main, _1080to480Config)
169 void _1080to480Main::reduce_field(VFrame *output, VFrame *input, int src_field, int dst_field)
171 int w = input->get_w();
172 int h = input->get_h();
174 if(h > output->get_h()) h = output->get_h();
175 if(w > output->get_w()) h = output->get_w();
177 #define REDUCE_MACRO(type, temp, components) \
178 for(int i = 0; i < OUT_ROWS; i++) \
180 int in_number1 = dst_field * 2 + src_field + (int)(i * 2) * 2; \
181 int in_number2 = in_number1 + 2; \
182 int in_number3 = in_number2 + 2; \
183 int in_number4 = in_number3 + 2; \
184 int out_number = dst_field + i * 2; \
186 if(in_number1 >= h) in_number1 = h - 1; \
187 if(in_number2 >= h) in_number2 = h - 1; \
188 if(in_number3 >= h) in_number3 = h - 1; \
189 if(in_number4 >= h) in_number4 = h - 1; \
190 if(out_number >= h) out_number = h - 1; \
192 type *in_row1 = (type*)input->get_rows()[in_number1]; \
193 type *in_row2 = (type*)input->get_rows()[in_number2]; \
194 type *in_row3 = (type*)input->get_rows()[in_number3]; \
195 type *in_row4 = (type*)input->get_rows()[in_number4]; \
196 type *out_row = (type*)output->get_rows()[out_number]; \
198 for(int j = 0; j < w * components; j++) \
200 *out_row++ = ((temp)*in_row1++ + \
203 (temp)*in_row4++) / 4; \
207 switch(input->get_color_model())
211 REDUCE_MACRO(unsigned char, int64_t, 3);
214 REDUCE_MACRO(float, float, 3);
218 REDUCE_MACRO(unsigned char, int64_t, 4);
221 REDUCE_MACRO(float, float, 4);
225 REDUCE_MACRO(uint16_t, int64_t, 3);
227 case BC_RGBA16161616:
228 case BC_YUVA16161616:
229 REDUCE_MACRO(uint16_t, int64_t, 4);
235 int _1080to480Main::process_realtime(VFrame *input, VFrame *output)
237 load_configuration();
240 temp = new VFrame(input->get_w(), input->get_h(), input->get_color_model(), 0);
244 reduce_field(temp, input, config.first_field == 0 ? 0 : 1, 0);
245 reduce_field(temp, input, config.first_field == 0 ? 1 : 0, 1);
247 output->copy_from(temp);
253 void _1080to480Main::save_data(KeyFrame *keyframe)
256 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
257 output.tag.set_title("1080TO480");
258 output.tag.set_property("FIRST_FIELD", config.first_field);
260 output.tag.set_title("/1080TO480");
262 output.append_newline();
263 output.terminate_string();
266 void _1080to480Main::read_data(KeyFrame *keyframe)
269 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
271 while(!input.read_tag())
273 if(input.tag.title_is("1080TO480"))
275 config.first_field = input.tag.get_property("FIRST_FIELD", config.first_field);
280 void _1080to480Main::update_gui()
284 load_configuration();
285 _1080to480Window *window = (_1080to480Window *)thread->window;
286 window->lock_window();
287 window->set_first_field(config.first_field, 0);
288 window->unlock_window();