3 #include "deinterlace.h"
4 #include "deinterwindow.h"
23 REGISTER_PLUGIN(DeInterlaceMain)
28 DeInterlaceConfig::DeInterlaceConfig()
30 mode = DEINTERLACE_EVEN;
35 int DeInterlaceConfig::equivalent(DeInterlaceConfig &that)
37 return mode == that.mode &&
38 adaptive == that.adaptive &&
39 threshold == that.threshold;
42 void DeInterlaceConfig::copy_from(DeInterlaceConfig &that)
45 adaptive = that.adaptive;
46 threshold = that.threshold;
49 void DeInterlaceConfig::interpolate(DeInterlaceConfig &prev,
50 DeInterlaceConfig &next,
53 int64_t current_frame)
61 DeInterlaceMain::DeInterlaceMain(PluginServer *server)
62 : PluginVClient(server)
64 PLUGIN_CONSTRUCTOR_MACRO
68 DeInterlaceMain::~DeInterlaceMain()
70 PLUGIN_DESTRUCTOR_MACRO
74 char* DeInterlaceMain::plugin_title() { return N_("Deinterlace"); }
75 int DeInterlaceMain::is_realtime() { return 1; }
79 #define DEINTERLACE_EVEN_MACRO(type, components, dominance) \
81 int w = input->get_w(); \
82 int h = input->get_h(); \
84 for(int i = 0; i < h - 1; i += 2) \
86 type *input_row = (type*)input->get_rows()[dominance ? i + 1 : i]; \
87 type *output_row1 = (type*)output->get_rows()[i]; \
88 type *output_row2 = (type*)output->get_rows()[i + 1]; \
89 memcpy(output_row1, input_row, w * components * sizeof(type)); \
90 memcpy(output_row2, input_row, w * components * sizeof(type)); \
94 #define DEINTERLACE_AVG_EVEN_MACRO(type, temp_type, components, dominance) \
96 int w = input->get_w(); \
97 int h = input->get_h(); \
100 type **in_rows = (type**)input->get_rows(); \
101 type **out_rows = (type**)temp->get_rows(); \
103 temp_type abs_diff = 0, total = 0; \
105 for(int i = 0; i < max_h; i += 2) \
107 int in_number1 = dominance ? i - 1 : i + 0; \
108 int in_number2 = dominance ? i + 1 : i + 2; \
109 int out_number1 = dominance ? i - 1 : i; \
110 int out_number2 = dominance ? i : i + 1; \
111 in_number1 = MAX(in_number1, 0); \
112 in_number2 = MIN(in_number2, max_h); \
113 out_number1 = MAX(out_number1, 0); \
114 out_number2 = MIN(out_number2, max_h); \
116 type *input_row1 = in_rows[in_number1]; \
117 type *input_row2 = in_rows[in_number2]; \
118 type *input_row3 = in_rows[out_number2]; \
119 type *temp_row1 = out_rows[out_number1]; \
120 type *temp_row2 = out_rows[out_number2]; \
122 temp_type accum_r, accum_b, accum_g, accum_a; \
124 memcpy(temp_row1, input_row1, w * components * sizeof(type)); \
125 for(int j = 0; j < w; j++) \
127 accum_r = (*input_row1++) + (*input_row2++); \
128 accum_g = (*input_row1++) + (*input_row2++); \
129 accum_b = (*input_row1++) + (*input_row2++); \
130 if(components == 4) \
131 accum_a = (*input_row1++) + (*input_row2++); \
137 total += *input_row3; \
138 sum = ((temp_type)*input_row3++) - accum_r; \
139 abs_diff += (sum < 0 ? -sum : sum); \
140 *temp_row2++ = accum_r; \
142 total += *input_row3; \
143 sum = ((temp_type)*input_row3++) - accum_g; \
144 abs_diff += (sum < 0 ? -sum : sum); \
145 *temp_row2++ = accum_g; \
147 total += *input_row3; \
148 sum = ((temp_type)*input_row3++) - accum_b; \
149 abs_diff += (sum < 0 ? -sum : sum); \
150 *temp_row2++ = accum_b; \
152 if(components == 4) \
154 total += *input_row3; \
155 sum = ((temp_type)*input_row3++) - accum_a; \
156 abs_diff += (sum < 0 ? -sum : sum); \
157 *temp_row2++ = accum_a; \
162 temp_type threshold = (temp_type)total * config.threshold / THRESHOLD_SCALAR; \
163 /* printf("total=%lld threshold=%lld abs_diff=%lld\n", total, threshold, abs_diff); */ \
164 if(abs_diff > threshold || !config.adaptive) \
166 output->copy_from(temp); \
167 changed_rows = 240; \
171 output->copy_from(input); \
177 #define DEINTERLACE_AVG_MACRO(type, temp_type, components) \
179 int w = input->get_w(); \
180 int h = input->get_h(); \
182 for(int i = 0; i < h - 1; i += 2) \
184 type *input_row1 = (type*)input->get_rows()[i]; \
185 type *input_row2 = (type*)input->get_rows()[i + 1]; \
186 type *output_row1 = (type*)output->get_rows()[i]; \
187 type *output_row2 = (type*)output->get_rows()[i + 1]; \
190 for(int j = 0; j < w * components; j++) \
192 result = ((temp_type)input_row1[j] + input_row2[j]) / 2; \
193 output_row1[j] = result; \
194 output_row2[j] = result; \
199 #define DEINTERLACE_SWAP_MACRO(type, components, dominance) \
201 int w = input->get_w(); \
202 int h = input->get_h(); \
204 for(int i = dominance; i < h - 1; i += 2) \
206 type *input_row1 = (type*)input->get_rows()[i]; \
207 type *input_row2 = (type*)input->get_rows()[i + 1]; \
208 type *output_row1 = (type*)output->get_rows()[i]; \
209 type *output_row2 = (type*)output->get_rows()[i + 1]; \
212 for(int j = 0; j < w * components; j++) \
214 temp1 = input_row1[j]; \
215 temp2 = input_row2[j]; \
216 output_row1[j] = temp2; \
217 output_row2[j] = temp1; \
223 void DeInterlaceMain::deinterlace_even(VFrame *input, VFrame *output, int dominance)
225 switch(input->get_color_model())
229 DEINTERLACE_EVEN_MACRO(unsigned char, 3, dominance);
232 DEINTERLACE_EVEN_MACRO(float, 3, dominance);
236 DEINTERLACE_EVEN_MACRO(unsigned char, 4, dominance);
239 DEINTERLACE_EVEN_MACRO(float, 4, dominance);
243 DEINTERLACE_EVEN_MACRO(uint16_t, 3, dominance);
245 case BC_RGBA16161616:
246 case BC_YUVA16161616:
247 DEINTERLACE_EVEN_MACRO(uint16_t, 4, dominance);
252 void DeInterlaceMain::deinterlace_avg_even(VFrame *input, VFrame *output, int dominance)
254 switch(input->get_color_model())
258 DEINTERLACE_AVG_EVEN_MACRO(unsigned char, int64_t, 3, dominance);
261 DEINTERLACE_AVG_EVEN_MACRO(float, double, 3, dominance);
265 DEINTERLACE_AVG_EVEN_MACRO(unsigned char, int64_t, 4, dominance);
268 DEINTERLACE_AVG_EVEN_MACRO(float, double, 4, dominance);
272 DEINTERLACE_AVG_EVEN_MACRO(uint16_t, int64_t, 3, dominance);
274 case BC_RGBA16161616:
275 case BC_YUVA16161616:
276 DEINTERLACE_AVG_EVEN_MACRO(uint16_t, int64_t, 4, dominance);
281 void DeInterlaceMain::deinterlace_avg(VFrame *input, VFrame *output)
283 switch(input->get_color_model())
287 DEINTERLACE_AVG_MACRO(unsigned char, uint64_t, 3);
290 DEINTERLACE_AVG_MACRO(float, double, 3);
294 DEINTERLACE_AVG_MACRO(unsigned char, uint64_t, 4);
297 DEINTERLACE_AVG_MACRO(float, double, 4);
301 DEINTERLACE_AVG_MACRO(uint16_t, uint64_t, 3);
303 case BC_RGBA16161616:
304 case BC_YUVA16161616:
305 DEINTERLACE_AVG_MACRO(uint16_t, uint64_t, 4);
310 void DeInterlaceMain::deinterlace_swap(VFrame *input, VFrame *output, int dominance)
312 switch(input->get_color_model())
316 DEINTERLACE_SWAP_MACRO(unsigned char, 3, dominance);
319 DEINTERLACE_SWAP_MACRO(float, 3, dominance);
323 DEINTERLACE_SWAP_MACRO(unsigned char, 4, dominance);
326 DEINTERLACE_SWAP_MACRO(float, 4, dominance);
330 DEINTERLACE_SWAP_MACRO(uint16_t, 3, dominance);
332 case BC_RGBA16161616:
333 case BC_YUVA16161616:
334 DEINTERLACE_SWAP_MACRO(uint16_t, 4, dominance);
340 int DeInterlaceMain::process_realtime(VFrame *input, VFrame *output)
342 changed_rows = input->get_h();
343 load_configuration();
348 input->get_color_model());
352 case DEINTERLACE_NONE:
353 output->copy_from(input);
355 case DEINTERLACE_EVEN:
356 deinterlace_even(input, output, 0);
358 case DEINTERLACE_ODD:
359 deinterlace_even(input, output, 1);
361 case DEINTERLACE_AVG:
362 deinterlace_avg(input, output);
364 case DEINTERLACE_AVG_EVEN:
365 deinterlace_avg_even(input, output, 0);
367 case DEINTERLACE_AVG_ODD:
368 deinterlace_avg_even(input, output, 1);
370 case DEINTERLACE_SWAP_ODD:
371 deinterlace_swap(input, output, 1);
373 case DEINTERLACE_SWAP_EVEN:
374 deinterlace_swap(input, output, 0);
377 send_render_gui(&changed_rows);
381 void DeInterlaceMain::render_gui(void *data)
385 thread->window->lock_window();
386 char string[BCTEXTLEN];
387 thread->window->get_status_string(string, *(int*)data);
388 thread->window->status->update(string);
389 thread->window->flush();
390 thread->window->unlock_window();
394 SHOW_GUI_MACRO(DeInterlaceMain, DeInterlaceThread)
395 RAISE_WINDOW_MACRO(DeInterlaceMain)
396 SET_STRING_MACRO(DeInterlaceMain)
397 NEW_PICON_MACRO(DeInterlaceMain)
398 LOAD_CONFIGURATION_MACRO(DeInterlaceMain, DeInterlaceConfig)
401 int DeInterlaceMain::load_defaults()
403 char directory[BCTEXTLEN], string[BCTEXTLEN];
404 sprintf(directory, "%sdeinterlace.rc", BCASTDIR);
406 defaults = new Defaults(directory);
408 config.mode = defaults->get("MODE", config.mode);
409 config.adaptive = defaults->get("ADAPTIVE", config.adaptive);
410 config.threshold = defaults->get("THRESHOLD", config.threshold);
415 int DeInterlaceMain::save_defaults()
417 defaults->update("MODE", config.mode);
418 defaults->update("ADAPTIVE", config.adaptive);
419 defaults->update("THRESHOLD", config.threshold);
424 void DeInterlaceMain::save_data(KeyFrame *keyframe)
427 output.set_shared_string(keyframe->data, MESSAGESIZE);
428 output.tag.set_title("DEINTERLACE");
429 output.tag.set_property("MODE", config.mode);
430 output.tag.set_property("ADAPTIVE", config.adaptive);
431 output.tag.set_property("THRESHOLD", config.threshold);
433 output.terminate_string();
436 void DeInterlaceMain::read_data(KeyFrame *keyframe)
439 input.set_shared_string(keyframe->data, strlen(keyframe->data));
441 while(!input.read_tag())
443 if(input.tag.title_is("DEINTERLACE"))
445 config.mode = input.tag.get_property("MODE", config.mode);
446 config.adaptive = input.tag.get_property("ADAPTIVE", config.adaptive);
447 config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
453 void DeInterlaceMain::update_gui()
457 load_configuration();
458 thread->window->lock_window();
459 thread->window->set_mode(config.mode, 0);
460 thread->window->adaptive->update(config.adaptive);
461 thread->window->threshold->update(config.threshold);
462 thread->window->unlock_window();