3 #include "deinterlace.h"
4 #include "deinterwindow.h"
12 #define _(String) gettext(String)
13 #define gettext_noop(String) String
14 #define N_(String) gettext_noop (String)
26 REGISTER_PLUGIN(DeInterlaceMain)
31 DeInterlaceConfig::DeInterlaceConfig()
33 mode = DEINTERLACE_EVEN;
38 int DeInterlaceConfig::equivalent(DeInterlaceConfig &that)
40 return mode == that.mode &&
41 adaptive == that.adaptive &&
42 threshold == that.threshold;
45 void DeInterlaceConfig::copy_from(DeInterlaceConfig &that)
48 adaptive = that.adaptive;
49 threshold = that.threshold;
52 void DeInterlaceConfig::interpolate(DeInterlaceConfig &prev,
53 DeInterlaceConfig &next,
56 int64_t current_frame)
64 DeInterlaceMain::DeInterlaceMain(PluginServer *server)
65 : PluginVClient(server)
67 PLUGIN_CONSTRUCTOR_MACRO
71 DeInterlaceMain::~DeInterlaceMain()
73 PLUGIN_DESTRUCTOR_MACRO
77 char* DeInterlaceMain::plugin_title() { return _("Deinterlace"); }
78 int DeInterlaceMain::is_realtime() { return 1; }
82 #define DEINTERLACE_EVEN_MACRO(type, components, dominance, max) \
84 int w = input->get_w(); \
85 int h = input->get_h(); \
87 for(int i = 0; i < h - 1; i += 2) \
89 type *input_row = (type*)input->get_rows()[dominance ? i + 1 : i]; \
90 type *output_row1 = (type*)output->get_rows()[i]; \
91 type *output_row2 = (type*)output->get_rows()[i + 1]; \
92 memcpy(output_row1, input_row, w * components * sizeof(type)); \
93 memcpy(output_row2, input_row, w * components * sizeof(type)); \
97 #define DEINTERLACE_AVG_EVEN_MACRO(type, components, dominance, max) \
99 int w = input->get_w(); \
100 int h = input->get_h(); \
103 type **in_rows = (type**)input->get_rows(); \
104 type **out_rows = (type**)temp->get_rows(); \
106 int64_t abs_diff = 0, total = 0; \
108 for(int i = 0; i < max_h; i += 2) \
110 int in_number1 = dominance ? i - 1 : i + 0; \
111 int in_number2 = dominance ? i + 1 : i + 2; \
112 int out_number1 = dominance ? i - 1 : i; \
113 int out_number2 = dominance ? i : i + 1; \
114 in_number1 = MAX(in_number1, 0); \
115 in_number2 = MIN(in_number2, max_h); \
116 out_number1 = MAX(out_number1, 0); \
117 out_number2 = MIN(out_number2, max_h); \
119 type *input_row1 = in_rows[in_number1]; \
120 type *input_row2 = in_rows[in_number2]; \
121 type *input_row3 = in_rows[out_number2]; \
122 type *temp_row1 = out_rows[out_number1]; \
123 type *temp_row2 = out_rows[out_number2]; \
125 int64_t accum_r, accum_b, accum_g, accum_a; \
127 memcpy(temp_row1, input_row1, w * components * sizeof(type)); \
128 for(int j = 0; j < w; j++) \
130 accum_r = (*input_row1++) + (*input_row2++); \
131 accum_g = (*input_row1++) + (*input_row2++); \
132 accum_b = (*input_row1++) + (*input_row2++); \
133 if(components == 4) \
134 accum_a = (*input_row1++) + (*input_row2++); \
140 total += *input_row3; \
141 sum = ((int)*input_row3++) - accum_r; \
142 abs_diff += (sum < 0 ? -sum : sum); \
143 *temp_row2++ = accum_r; \
145 total += *input_row3; \
146 sum = ((int)*input_row3++) - accum_g; \
147 abs_diff += (sum < 0 ? -sum : sum); \
148 *temp_row2++ = accum_g; \
150 total += *input_row3; \
151 sum = ((int)*input_row3++) - accum_b; \
152 abs_diff += (sum < 0 ? -sum : sum); \
153 *temp_row2++ = accum_b; \
155 if(components == 4) \
157 total += *input_row3; \
158 sum = ((int)*input_row3++) - accum_a; \
159 abs_diff += (sum < 0 ? -sum : sum); \
160 *temp_row2++ = accum_a; \
165 int64_t threshold = (int64_t)total * config.threshold / THRESHOLD_SCALAR; \
166 /* printf("total=%lld threshold=%lld abs_diff=%lld\n", total, threshold, abs_diff); */ \
167 if(abs_diff > threshold || !config.adaptive) \
169 output->copy_from(temp); \
170 changed_rows = 240; \
174 output->copy_from(input); \
180 #define DEINTERLACE_AVG_MACRO(type, components) \
182 int w = input->get_w(); \
183 int h = input->get_h(); \
185 for(int i = 0; i < h - 1; i += 2) \
187 type *input_row1 = (type*)input->get_rows()[i]; \
188 type *input_row2 = (type*)input->get_rows()[i + 1]; \
189 type *output_row1 = (type*)output->get_rows()[i]; \
190 type *output_row2 = (type*)output->get_rows()[i + 1]; \
193 for(int j = 0; j < w * components; j++) \
195 result = ((uint64_t)input_row1[j] + input_row2[j]) >> 1; \
196 output_row1[j] = result; \
197 output_row2[j] = result; \
202 #define DEINTERLACE_SWAP_MACRO(type, components, dominance) \
204 int w = input->get_w(); \
205 int h = input->get_h(); \
207 for(int i = dominance; i < h - 1; i += 2) \
209 type *input_row1 = (type*)input->get_rows()[i]; \
210 type *input_row2 = (type*)input->get_rows()[i + 1]; \
211 type *output_row1 = (type*)output->get_rows()[i]; \
212 type *output_row2 = (type*)output->get_rows()[i + 1]; \
215 for(int j = 0; j < w * components; j++) \
217 temp1 = input_row1[j]; \
218 temp2 = input_row2[j]; \
219 output_row1[j] = temp2; \
220 output_row2[j] = temp1; \
226 void DeInterlaceMain::deinterlace_even(VFrame *input, VFrame *output, int dominance)
228 switch(input->get_color_model())
232 DEINTERLACE_EVEN_MACRO(unsigned char, 3, dominance, 0xff);
236 DEINTERLACE_EVEN_MACRO(unsigned char, 4, dominance, 0xff);
240 DEINTERLACE_EVEN_MACRO(uint16_t, 3, dominance, 0xffff);
242 case BC_RGBA16161616:
243 case BC_YUVA16161616:
244 DEINTERLACE_EVEN_MACRO(uint16_t, 4, dominance, 0xffff);
249 void DeInterlaceMain::deinterlace_avg_even(VFrame *input, VFrame *output, int dominance)
251 switch(input->get_color_model())
255 DEINTERLACE_AVG_EVEN_MACRO(unsigned char, 3, dominance, 0xff);
259 DEINTERLACE_AVG_EVEN_MACRO(unsigned char, 4, dominance, 0xff);
263 DEINTERLACE_AVG_EVEN_MACRO(uint16_t, 3, dominance, 0xffff);
265 case BC_RGBA16161616:
266 case BC_YUVA16161616:
267 DEINTERLACE_AVG_EVEN_MACRO(uint16_t, 4, dominance, 0xffff);
272 void DeInterlaceMain::deinterlace_avg(VFrame *input, VFrame *output)
274 switch(input->get_color_model())
278 DEINTERLACE_AVG_MACRO(unsigned char, 3);
282 DEINTERLACE_AVG_MACRO(unsigned char, 4);
286 DEINTERLACE_AVG_MACRO(uint16_t, 3);
288 case BC_RGBA16161616:
289 case BC_YUVA16161616:
290 DEINTERLACE_AVG_MACRO(uint16_t, 4);
295 void DeInterlaceMain::deinterlace_swap(VFrame *input, VFrame *output, int dominance)
297 switch(input->get_color_model())
301 DEINTERLACE_SWAP_MACRO(unsigned char, 3, dominance);
305 DEINTERLACE_SWAP_MACRO(unsigned char, 4, dominance);
309 DEINTERLACE_SWAP_MACRO(uint16_t, 3, dominance);
311 case BC_RGBA16161616:
312 case BC_YUVA16161616:
313 DEINTERLACE_SWAP_MACRO(uint16_t, 4, dominance);
319 int DeInterlaceMain::process_realtime(VFrame *input, VFrame *output)
321 changed_rows = input->get_h();
322 load_configuration();
327 input->get_color_model());
331 case DEINTERLACE_NONE:
332 output->copy_from(input);
334 case DEINTERLACE_EVEN:
335 deinterlace_even(input, output, 0);
337 case DEINTERLACE_ODD:
338 deinterlace_even(input, output, 1);
340 case DEINTERLACE_AVG:
341 deinterlace_avg(input, output);
343 case DEINTERLACE_AVG_EVEN:
344 deinterlace_avg_even(input, output, 0);
346 case DEINTERLACE_AVG_ODD:
347 deinterlace_avg_even(input, output, 1);
349 case DEINTERLACE_SWAP_ODD:
350 deinterlace_swap(input, output, 1);
352 case DEINTERLACE_SWAP_EVEN:
353 deinterlace_swap(input, output, 0);
356 send_render_gui(&changed_rows);
360 void DeInterlaceMain::render_gui(void *data)
364 thread->window->lock_window();
365 char string[BCTEXTLEN];
366 thread->window->get_status_string(string, *(int*)data);
367 thread->window->status->update(string);
368 thread->window->flush();
369 thread->window->unlock_window();
373 SHOW_GUI_MACRO(DeInterlaceMain, DeInterlaceThread)
374 RAISE_WINDOW_MACRO(DeInterlaceMain)
375 SET_STRING_MACRO(DeInterlaceMain)
376 NEW_PICON_MACRO(DeInterlaceMain)
377 LOAD_CONFIGURATION_MACRO(DeInterlaceMain, DeInterlaceConfig)
380 int DeInterlaceMain::load_defaults()
382 char directory[BCTEXTLEN], string[BCTEXTLEN];
383 sprintf(directory, "%sdeinterlace.rc", BCASTDIR);
385 defaults = new Defaults(directory);
387 config.mode = defaults->get("MODE", config.mode);
388 config.adaptive = defaults->get("ADAPTIVE", config.adaptive);
389 config.threshold = defaults->get("THRESHOLD", config.threshold);
394 int DeInterlaceMain::save_defaults()
396 defaults->update("MODE", config.mode);
397 defaults->update("ADAPTIVE", config.adaptive);
398 defaults->update("THRESHOLD", config.threshold);
403 void DeInterlaceMain::save_data(KeyFrame *keyframe)
406 output.set_shared_string(keyframe->data, MESSAGESIZE);
407 output.tag.set_title("DEINTERLACE");
408 output.tag.set_property("MODE", config.mode);
409 output.tag.set_property("ADAPTIVE", config.adaptive);
410 output.tag.set_property("THRESHOLD", config.threshold);
412 output.terminate_string();
415 void DeInterlaceMain::read_data(KeyFrame *keyframe)
418 input.set_shared_string(keyframe->data, strlen(keyframe->data));
420 while(!input.read_tag())
422 if(input.tag.title_is("DEINTERLACE"))
424 config.mode = input.tag.get_property("MODE", config.mode);
425 config.adaptive = input.tag.get_property("ADAPTIVE", config.adaptive);
426 config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
432 void DeInterlaceMain::update_gui()
436 load_configuration();
437 thread->window->lock_window();
438 thread->window->set_mode(config.mode, 0);
439 thread->window->adaptive->update(config.adaptive);
440 thread->window->threshold->update(config.threshold);
441 thread->window->unlock_window();