9 #include "overlayframe.h"
12 OverlayFrame::OverlayFrame(int cpus)
17 scaletranslate_engine = 0;
22 OverlayFrame::~OverlayFrame()
24 //printf("OverlayFrame::~OverlayFrame 1\n");
25 if(temp_frame) delete temp_frame;
26 if(scale_engine) delete scale_engine;
27 if(translate_engine) delete translate_engine;
28 if(blend_engine) delete blend_engine;
29 if(scaletranslate_engine) delete scaletranslate_engine;
30 //printf("OverlayFrame::~OverlayFrame 2\n");
42 // (255 * 255 + 0 * 0) / 255 = 255
43 // (255 * 127 + 255 * (255 - 127)) / 255 = 255
45 // (65535 * 65535 + 0 * 0) / 65535 = 65535
46 // (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535
49 // Branch prediction 4 U
51 #define BLEND_3(max, type) \
55 /* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \
58 case TRANSFER_DIVIDE: \
59 r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
60 g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
61 b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
62 r = (r * opacity + output[0] * transparency) / max; \
63 g = (g * opacity + output[1] * transparency) / max; \
64 b = (b * opacity + output[2] * transparency) / max; \
66 case TRANSFER_MULTIPLY: \
67 r = ((int64_t)input1 * output[0]) / max; \
68 g = ((int64_t)input2 * output[1]) / max; \
69 b = ((int64_t)input3 * output[2]) / max; \
70 r = (r * opacity + output[0] * transparency) / max; \
71 g = (g * opacity + output[1] * transparency) / max; \
72 b = (b * opacity + output[2] * transparency) / max; \
74 case TRANSFER_SUBTRACT: \
75 r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \
76 g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \
77 b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \
79 case TRANSFER_ADDITION: \
80 r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \
81 g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \
82 b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \
84 case TRANSFER_REPLACE: \
89 case TRANSFER_NORMAL: \
90 r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \
91 g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \
92 b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \
96 output[0] = (type)CLIP(r, 0, max); \
97 output[1] = (type)CLIP(g, 0, max); \
98 output[2] = (type)CLIP(b, 0, max); \
105 // Blending equations are drastically different for 3 and 4 components
106 #define BLEND_4(max, type) \
108 int64_t r, g, b, a; \
109 int64_t pixel_opacity, pixel_transparency; \
111 pixel_opacity = opacity * input4 / max; \
112 pixel_transparency = (max - pixel_opacity) * output[3] / max; \
116 case TRANSFER_DIVIDE: \
117 r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
118 g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
119 b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
120 r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
121 g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
122 b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
123 a = input4 > output[3] ? input4 : output[3]; \
125 case TRANSFER_MULTIPLY: \
126 r = ((int64_t)input1 * output[0]) / max; \
127 g = ((int64_t)input2 * output[1]) / max; \
128 b = ((int64_t)input3 * output[2]) / max; \
129 r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
130 g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
131 b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
132 a = input4 > output[3] ? input4 : output[3]; \
134 case TRANSFER_SUBTRACT: \
135 r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
136 g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
137 b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
138 a = input4 > output[3] ? input4 : output[3]; \
140 case TRANSFER_ADDITION: \
141 r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
142 g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
143 b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
144 a = input4 > output[3] ? input4 : output[3]; \
146 case TRANSFER_REPLACE: \
152 case TRANSFER_NORMAL: \
153 r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \
154 g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \
155 b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \
156 a = input4 > output[3] ? input4 : output[3]; \
160 output[0] = (type)CLIP(r, 0, max); \
161 output[1] = (type)CLIP(g, 0, max); \
162 output[2] = (type)CLIP(b, 0, max); \
163 output[3] = (type)a; \
173 // Bicubic algorithm using multiprocessors
174 // input -> scale nearest integer boundaries -> temp -> translation -> blend -> output
176 // Nearest neighbor algorithm using multiprocessors for blending
177 // input -> scale + translate -> blend -> output
180 int OverlayFrame::overlay(VFrame *output,
190 float alpha, // 0 - 1
192 int interpolation_type)
194 float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
195 float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
197 //printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha);
201 out_x1 += -in_x1 * w_scale;
205 if(in_x1 >= input->get_w())
207 out_x1 -= (in_x1 - input->get_w()) * w_scale;
208 in_x1 = input->get_w();
213 out_y1 += -in_y1 * h_scale;
217 if(in_y1 >= input->get_h())
219 out_y1 -= (in_y1 - input->get_h()) * h_scale;
220 in_y1 = input->get_h();
225 out_x2 += -in_x2 * w_scale;
229 if(in_x2 >= input->get_w())
231 out_x2 -= (in_x2 - input->get_w()) * w_scale;
232 in_x2 = input->get_w();
237 out_y2 += -in_y2 * h_scale;
241 if(in_y2 >= input->get_h())
243 out_y2 -= (in_y2 - input->get_h()) * h_scale;
244 in_y2 = input->get_h();
249 in_x1 += -out_x1 / w_scale;
253 if(out_x1 >= output->get_w())
255 in_x1 -= (out_x1 - output->get_w()) / w_scale;
256 out_x1 = output->get_w();
261 in_y1 += -out_y1 / h_scale;
265 if(out_y1 >= output->get_h())
267 in_y1 -= (out_y1 - output->get_h()) / h_scale;
268 out_y1 = output->get_h();
273 in_x2 += -out_x2 / w_scale;
277 if(out_x2 >= output->get_w())
279 in_x2 -= (out_x2 - output->get_w()) / w_scale;
280 out_x2 = output->get_w();
285 in_y2 += -out_y2 / h_scale;
289 if(out_y2 >= output->get_h())
291 in_y2 -= (out_y2 - output->get_h()) / h_scale;
292 out_y2 = output->get_h();
299 float in_w = in_x2 - in_x1;
300 float in_h = in_y2 - in_y1;
301 float out_w = out_x2 - out_x1;
302 float out_h = out_y2 - out_y1;
303 // Input for translation operation
304 VFrame *translation_input = input;
308 // printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1,
321 // ****************************************************************************
322 // Transfer to temp buffer by scaling nearest integer boundaries
323 // ****************************************************************************
324 if(interpolation_type != NEAREST_NEIGHBOR &&
325 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
327 // Create integer boundaries for interpolation
328 int in_x1_int = (int)in_x1;
329 int in_y1_int = (int)in_y1;
330 int in_x2_int = MIN((int)ceil(in_x2), input->get_w());
331 int in_y2_int = MIN((int)ceil(in_y2), input->get_h());
333 // Dimensions of temp frame. Integer boundaries scaled.
334 int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int));
335 int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int));
336 VFrame *scale_output;
340 #define NO_TRANSLATION1 \
341 (EQUIV(in_x1, 0) && \
343 EQUIV(out_x1, 0) && \
344 EQUIV(out_y1, 0) && \
345 EQUIV(in_x2, in_x2_int) && \
346 EQUIV(in_y2, in_y2_int) && \
347 EQUIV(out_x2, temp_w) && \
348 EQUIV(out_y2, temp_h))
352 (EQUIV(alpha, 1) && \
353 (mode == TRANSFER_REPLACE || \
354 (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
360 // Prepare destination for operation
362 // No translation and no blending. The blending operation is built into the
363 // translation unit but not the scaling unit.
365 if(NO_TRANSLATION1 &&
368 // printf("OverlayFrame::overlay input -> output\n");
370 scale_output = output;
371 translation_input = 0;
374 // If translation or blending
375 // input -> nearest integer boundary temp
378 (temp_frame->get_w() != temp_w ||
379 temp_frame->get_h() != temp_h))
387 temp_frame = new VFrame(0,
390 input->get_color_model(),
393 //printf("OverlayFrame::overlay input -> temp\n");
396 temp_frame->clear_frame();
398 // printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n",
400 scale_output = temp_frame;
401 translation_input = scale_output;
403 // Adjust input coordinates to reflect new scaled coordinates.
404 in_x1 = (in_x1 - in_x1_int) * w_scale;
405 in_y1 = (in_y1 - in_y1_int) * h_scale;
406 in_x2 = (in_x2 - in_x1_int) * w_scale;
407 in_y2 = (in_y2 - in_y1_int) * h_scale;
412 //printf("Overlay 1\n");
414 // Scale input -> scale_output
415 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
416 scale_engine->scale_output = scale_output;
417 scale_engine->scale_input = input;
418 scale_engine->w_scale = w_scale;
419 scale_engine->h_scale = h_scale;
420 scale_engine->in_x1_int = in_x1_int;
421 scale_engine->in_y1_int = in_y1_int;
422 scale_engine->out_w_int = temp_w;
423 scale_engine->out_h_int = temp_h;
424 scale_engine->interpolation_type = interpolation_type;
425 //printf("Overlay 2\n");
427 //printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int);
428 scale_engine->process_packages();
429 //printf("OverlayFrame::overlay ScaleEngine 2\n");
435 // printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
449 #define NO_TRANSLATION2 \
450 (EQUIV(in_x1, 0) && \
452 EQUIV(in_x2, translation_input->get_w()) && \
453 EQUIV(in_y2, translation_input->get_h()) && \
454 EQUIV(out_x1, 0) && \
455 EQUIV(out_y1, 0) && \
456 EQUIV(out_x2, output->get_w()) && \
457 EQUIV(out_y2, output->get_h())) \
460 (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
461 EQUIV(out_y2 - out_y1, in_y2 - in_y1))
466 //printf("OverlayFrame::overlay 4 %d\n", mode);
471 if(translation_input)
474 if( NO_TRANSLATION2 &&
478 //printf("OverlayFrame::overlay direct copy\n");
479 output->copy_from(translation_input);
483 if( NO_TRANSLATION2 &&
486 if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
489 blend_engine->output = output;
490 blend_engine->input = translation_input;
491 blend_engine->alpha = alpha;
492 blend_engine->mode = mode;
494 blend_engine->process_packages();
497 // Scale and translate using nearest neighbor
498 // Translation is exactly on integer boundaries
499 if(interpolation_type == NEAREST_NEIGHBOR ||
500 EQUIV(in_x1, (int)in_x1) &&
501 EQUIV(in_y1, (int)in_y1) &&
502 EQUIV(in_x2, (int)in_x2) &&
503 EQUIV(in_y2, (int)in_y2) &&
505 EQUIV(out_x1, (int)out_x1) &&
506 EQUIV(out_y1, (int)out_y1) &&
507 EQUIV(out_x2, (int)out_x2) &&
508 EQUIV(out_y2, (int)out_y2))
510 //printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n");
511 if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus);
514 scaletranslate_engine->output = output;
515 scaletranslate_engine->input = translation_input;
516 scaletranslate_engine->in_x1 = (int)in_x1;
517 scaletranslate_engine->in_y1 = (int)in_y1;
518 scaletranslate_engine->in_x2 = (int)in_x2;
519 scaletranslate_engine->in_y2 = (int)in_y2;
520 scaletranslate_engine->out_x1 = (int)out_x1;
521 scaletranslate_engine->out_y1 = (int)out_y1;
522 scaletranslate_engine->out_x2 = (int)out_x2;
523 scaletranslate_engine->out_y2 = (int)out_y2;
524 scaletranslate_engine->alpha = alpha;
525 scaletranslate_engine->mode = mode;
527 scaletranslate_engine->process_packages();
530 // Fractional translation
532 // Use fractional translation
533 // printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
543 //printf("Overlay 3\n");
544 if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
545 translate_engine->translate_output = output;
546 translate_engine->translate_input = translation_input;
547 translate_engine->translate_in_x1 = in_x1;
548 translate_engine->translate_in_y1 = in_y1;
549 translate_engine->translate_in_x2 = in_x2;
550 translate_engine->translate_in_y2 = in_y2;
551 translate_engine->translate_out_x1 = out_x1;
552 translate_engine->translate_out_y1 = out_y1;
553 translate_engine->translate_out_x2 = out_x2;
554 translate_engine->translate_out_y2 = out_y2;
555 translate_engine->translate_alpha = alpha;
556 translate_engine->translate_mode = mode;
557 //printf("Overlay 4\n");
559 //printf("OverlayFrame::overlay 5 %d\n", mode);
560 translate_engine->process_packages();
564 //printf("OverlayFrame::overlay 2\n");
575 ScalePackage::ScalePackage()
582 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
585 this->overlay = overlay;
586 this->engine = server;
589 ScaleUnit::~ScaleUnit()
595 #define BILINEAR(max, type, components) \
597 float k_y = 1.0 / scale_h; \
598 float k_x = 1.0 / scale_w; \
599 type **in_rows = (type**)input->get_rows(); \
600 type **out_rows = (type**)output->get_rows(); \
601 int out_h = pkg->out_row2 - pkg->out_row1; \
602 int in_h_int = input->get_h(); \
603 int in_w_int = input->get_w(); \
604 int *table_int_x1, *table_int_y1; \
605 int *table_int_x2, *table_int_y2; \
606 float *table_frac_x, *table_antifrac_x, *table_frac_y, *table_antifrac_y; \
608 tabulate_blinear(table_int_x1, \
617 tabulate_blinear(table_int_y1, \
627 for(int i = 0; i < out_h; i++) \
629 int i_y1 = table_int_y1[i]; \
630 int i_y2 = table_int_y2[i]; \
631 float a = table_frac_y[i]; \
632 float anti_a = table_antifrac_y[i]; \
633 type *in_row1 = in_rows[i_y1]; \
634 type *in_row2 = in_rows[i_y2]; \
635 type *out_row = out_rows[i + pkg->out_row1]; \
637 for(int j = 0; j < out_w_int; j++) \
639 int i_x1 = table_int_x1[j]; \
640 int i_x2 = table_int_x2[j]; \
641 float b = table_frac_x[j]; \
642 float anti_b = table_antifrac_x[j]; \
643 float output1r, output1g, output1b, output1a; \
644 float output2r, output2g, output2b, output2a; \
645 float output3r, output3g, output3b, output3a; \
646 float output4r, output4g, output4b, output4a; \
648 output1r = in_row1[i_x1 * components]; \
649 output1g = in_row1[i_x1 * components + 1]; \
650 output1b = in_row1[i_x1 * components + 2]; \
651 if(components == 4) output1a = in_row1[i_x1 * components + 3]; \
653 output2r = in_row1[i_x2 * components]; \
654 output2g = in_row1[i_x2 * components + 1]; \
655 output2b = in_row1[i_x2 * components + 2]; \
656 if(components == 4) output2a = in_row1[i_x2 * components + 3]; \
658 output3r = in_row2[i_x1 * components]; \
659 output3g = in_row2[i_x1 * components + 1]; \
660 output3b = in_row2[i_x1 * components + 2]; \
661 if(components == 4) output3a = in_row2[i_x1 * components + 3]; \
663 output4r = in_row2[i_x2 * components]; \
664 output4g = in_row2[i_x2 * components + 1]; \
665 output4b = in_row2[i_x2 * components + 2]; \
666 if(components == 4) output4a = in_row2[i_x2 * components + 3]; \
668 out_row[j * components] = \
669 (type)((anti_a) * (((anti_b) * output1r) + \
671 a * (((anti_b) * output3r) + \
673 out_row[j * components + 1] = \
674 (type)((anti_a) * (((anti_b) * output1g) + \
676 a * (((anti_b) * output3g) + \
678 out_row[j * components + 2] = \
679 (type)((anti_a) * (((anti_b) * output1b) + \
681 a * (((anti_b) * output3b) + \
683 if(components == 4) \
684 out_row[j * components + 3] = \
685 (type)((anti_a) * (((anti_b) * output1a) + \
687 a * (((anti_b) * output3a) + \
693 delete [] table_int_x1; \
694 delete [] table_int_x2; \
695 delete [] table_frac_x; \
696 delete [] table_antifrac_x; \
697 delete [] table_int_y1; \
698 delete [] table_int_y2; \
699 delete [] table_frac_y; \
700 delete [] table_antifrac_y; \
705 #define BICUBIC(max, type, components) \
707 float k_y = 1.0 / scale_h; \
708 float k_x = 1.0 / scale_w; \
709 type **in_rows = (type**)input->get_rows(); \
710 type **out_rows = (type**)output->get_rows(); \
711 float *bspline_x, *bspline_y; \
712 int *in_x_table, *in_y_table; \
713 int in_h_int = input->get_h(); \
714 int in_w_int = input->get_w(); \
716 tabulate_bicubic(bspline_x, \
724 tabulate_bicubic(bspline_y, \
732 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
734 for(int j = 0; j < out_w_int; j++) \
736 int i_x = (int)(k_x * j); \
737 float output1, output2, output3, output4; \
741 if(components == 4) \
743 int table_y = i * 4; \
746 for(int m = -1; m < 3; m++) \
748 float r1 = bspline_y[table_y]; \
749 int y = in_y_table[table_y]; \
750 int table_x = j * 4; \
752 for(int n = -1; n < 3; n++) \
754 float r2 = bspline_x[table_x]; \
755 int x = in_x_table[table_x]; \
756 float r_square = r1 * r2; \
758 output1 += r_square * in_rows[y][x * components]; \
759 output2 += r_square * in_rows[y][x * components + 1]; \
760 output3 += r_square * in_rows[y][x * components + 2]; \
761 if(components == 4) \
762 output4 += r_square * in_rows[y][x * components + 3]; \
770 out_rows[i][j * components] = (type)output1; \
771 out_rows[i][j * components + 1] = (type)output2; \
772 out_rows[i][j * components + 2] = (type)output3; \
773 if(components == 4) \
774 out_rows[i][j * components + 3] = (type)output4; \
779 delete [] bspline_x; \
780 delete [] bspline_y; \
781 delete [] in_x_table; \
782 delete [] in_y_table; \
788 // Pow function is not thread safe in Compaqt C
789 #define CUBE(x) ((x) * (x) * (x))
791 float ScaleUnit::cubic_bspline(float x)
795 if((x + 2.0F) <= 0.0F)
805 if((x + 1.0F) <= 0.0F)
823 if((x - 1.0F) <= 0.0F)
833 return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
837 void ScaleUnit::tabulate_bicubic(float* &coef_table,
845 coef_table = new float[pixels * 4];
846 coord_table = new int[pixels * 4];
847 for(int i = 0, j = 0; i < pixels; i++)
849 float f_x = (float)i * scale;
850 float a = f_x - floor(f_x);
852 for(float m = -1; m < 3; m++)
854 coef_table[j] = cubic_bspline(coefficient * (m - a));
855 coord_table[j] = start + (int)f_x + m;
856 CLAMP(coord_table[j], 0, total_pixels - 1);
863 void ScaleUnit::tabulate_blinear(int* &table_int1,
866 float* &table_antifrac,
873 table_int1 = new int[pixel2 - pixel1];
874 table_int2 = new int[pixel2 - pixel1];
875 table_frac = new float[pixel2 - pixel1];
876 table_antifrac = new float[pixel2 - pixel1];
878 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
880 float f_x = (float)i * scale;
881 int i_x = (int)floor(f_x);
882 float a = (f_x - floor(f_x));
884 table_int1[j] = i_x + start;
885 table_int2[j] = i_x + start + 1;
886 CLAMP(table_int1[j], 0, total_pixels - 1);
887 CLAMP(table_int2[j], 0, total_pixels - 1);
889 table_antifrac[j] = 1.0F - a;
890 //printf("ScaleUnit::tabulate_blinear %d %d %d\n", j, table_int1[j], table_int2[j]);
894 void ScaleUnit::process_package(LoadPackage *package)
896 ScalePackage *pkg = (ScalePackage*)package;
898 //printf("ScaleUnit::process_package 1\n");
899 // Arguments for macros
900 VFrame *output = engine->scale_output;
901 VFrame *input = engine->scale_input;
902 float scale_w = engine->w_scale;
903 float scale_h = engine->h_scale;
904 int in_x1_int = engine->in_x1_int;
905 int in_y1_int = engine->in_y1_int;
906 int out_h_int = engine->out_h_int;
907 int out_w_int = engine->out_w_int;
909 (input->get_color_model() == BC_YUV888 ||
910 input->get_color_model() == BC_YUVA8888 ||
911 input->get_color_model() == BC_YUV161616 ||
912 input->get_color_model() == BC_YUVA16161616);
914 //printf("ScaleUnit::process_package 2\n");
915 if(engine->interpolation_type == CUBIC_CUBIC ||
916 (engine->interpolation_type == CUBIC_LINEAR
917 && engine->w_scale > 1 &&
918 engine->h_scale > 1))
921 switch(engine->scale_input->get_color_model())
925 BICUBIC(0xff, unsigned char, 3);
930 BICUBIC(0xff, unsigned char, 4);
935 BICUBIC(0xffff, uint16_t, 3);
938 case BC_RGBA16161616:
939 case BC_YUVA16161616:
940 BICUBIC(0xffff, uint16_t, 4);
945 // Perform bilinear scaling input -> scale_output
947 switch(engine->scale_input->get_color_model())
951 BILINEAR(0xff, unsigned char, 3);
956 BILINEAR(0xff, unsigned char, 4);
961 BILINEAR(0xffff, uint16_t, 3);
964 case BC_RGBA16161616:
965 case BC_YUVA16161616:
966 BILINEAR(0xffff, uint16_t, 4);
970 //printf("ScaleUnit::process_package 3\n");
986 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
987 : LoadServer(cpus, cpus)
989 this->overlay = overlay;
992 ScaleEngine::~ScaleEngine()
996 void ScaleEngine::init_packages()
998 for(int i = 0; i < total_packages; i++)
1000 ScalePackage *package = (ScalePackage*)packages[i];
1001 package->out_row1 = out_h_int / total_packages * i;
1002 package->out_row2 = package->out_row1 + out_h_int / total_packages;
1004 if(i >= total_packages - 1)
1005 package->out_row2 = out_h_int;
1009 LoadClient* ScaleEngine::new_client()
1011 return new ScaleUnit(this, overlay);
1014 LoadPackage* ScaleEngine::new_package()
1016 return new ScalePackage;
1031 TranslatePackage::TranslatePackage()
1037 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
1038 : LoadClient(server)
1040 this->overlay = overlay;
1041 this->engine = server;
1044 TranslateUnit::~TranslateUnit()
1050 void TranslateUnit::translation_array(transfer_table* &table,
1061 float offset = out_x1 - in_x1;
1063 out_x1_int = (int)out_x1;
1064 out_x2_int = MIN((int)ceil(out_x2), out_total);
1065 out_w_int = out_x2_int - out_x1_int;
1067 table = new transfer_table[out_w_int];
1068 bzero(table, sizeof(transfer_table) * out_w_int);
1071 //printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1074 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
1076 transfer_table *entry = &table[out_x - out_x1_int];
1078 entry->in_x1 = (int)in_x;
1079 entry->in_x2 = (int)in_x + 1;
1081 // Get fraction of output pixel to fill
1082 entry->output_fraction = 1;
1086 entry->output_fraction -= out_x1 - out_x;
1089 if(out_x2 < out_x + 1)
1091 entry->output_fraction = (out_x2 - out_x);
1094 // Advance in_x until out_x_fraction is filled
1095 float out_x_fraction = entry->output_fraction;
1096 float in_x_fraction = floor(in_x + 1) - in_x;
1098 if(out_x_fraction <= in_x_fraction)
1100 entry->in_fraction1 = out_x_fraction;
1101 entry->in_fraction2 = 0.0;
1102 in_x += out_x_fraction;
1106 entry->in_fraction1 = in_x_fraction;
1107 in_x += out_x_fraction;
1108 entry->in_fraction2 = in_x - floor(in_x);
1111 // Clip in_x and zero out fraction. This doesn't work for YUV.
1112 if(entry->in_x2 >= in_total)
1114 entry->in_x2 = in_total - 1;
1115 entry->in_fraction2 = 0.0;
1118 if(entry->in_x1 >= in_total)
1120 entry->in_x1 = in_total - 1;
1121 entry->in_fraction1 = 0.0;
1123 // printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n",
1127 // entry->in_fraction1,
1128 // entry->in_fraction2,
1129 // entry->output_fraction);
1166 #define TRANSLATE(max, type, components, do_yuv) \
1169 type **in_rows = (type**)input->get_rows(); \
1170 type **out_rows = (type**)output->get_rows(); \
1172 /* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \
1173 /* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \
1175 unsigned int master_opacity = (int)(alpha * max + 0.5); \
1176 unsigned int master_transparency = max - master_opacity; \
1177 float zero_r, zero_g, zero_b; \
1179 zero_b = ((max + 1) >> 1) * (do_yuv); \
1180 zero_g = ((max + 1) >> 1) * (do_yuv); \
1182 /* printf("TRANSLATE %d\n", mode); */ \
1184 for(int i = row1; i < row2; i++) \
1186 int in_y1 = y_table[i - out_y1_int].in_x1; \
1187 int in_y2 = y_table[i - out_y1_int].in_x2; \
1188 float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \
1189 float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \
1190 float y_output_fraction = y_table[i - out_y1_int].output_fraction; \
1191 type *in_row1 = in_rows[(in_y1)]; \
1192 type *in_row2 = in_rows[(in_y2)]; \
1193 type *out_row = out_rows[i]; \
1195 for(int j = out_x1_int; j < out_x2_int; j++) \
1197 int in_x1 = x_table[j - out_x1_int].in_x1; \
1198 int in_x2 = x_table[j - out_x1_int].in_x2; \
1199 float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \
1200 float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \
1201 float x_output_fraction = x_table[j - out_x1_int].output_fraction; \
1202 type *output = &out_row[j * components]; \
1203 int input1, input2, input3, input4; \
1204 float fraction1 = x_fraction1 * y_fraction1; \
1205 float fraction2 = x_fraction2 * y_fraction1; \
1206 float fraction3 = x_fraction1 * y_fraction2; \
1207 float fraction4 = x_fraction2 * y_fraction2; \
1209 input1 = (int)(in_row1[in_x1 * components] * fraction1 + \
1210 in_row1[in_x2 * components] * fraction2 + \
1211 in_row2[in_x1 * components] * fraction3 + \
1212 in_row2[in_x2 * components] * fraction4 + 0.5); \
1214 /* Add chroma to fractional pixels */ \
1217 float extra_chroma = (1.0F - \
1221 fraction4) * zero_b; \
1222 input2 = (int)(in_row1[in_x1 * components + 1] * fraction1 + \
1223 in_row1[in_x2 * components + 1] * fraction2 + \
1224 in_row2[in_x1 * components + 1] * fraction3 + \
1225 in_row2[in_x2 * components + 1] * fraction4 + \
1226 extra_chroma + 0.5); \
1227 input3 = (int)(in_row1[in_x1 * components + 2] * fraction1 + \
1228 in_row1[in_x2 * components + 2] * fraction2 + \
1229 in_row2[in_x1 * components + 2] * fraction3 + \
1230 in_row2[in_x2 * components + 2] * fraction4 + \
1231 extra_chroma + 0.5); \
1235 input2 = (int)(in_row1[in_x1 * components + 1] * fraction1 + \
1236 in_row1[in_x2 * components + 1] * fraction2 + \
1237 in_row2[in_x1 * components + 1] * fraction3 + \
1238 in_row2[in_x2 * components + 1] * fraction4 + 0.5); \
1239 input3 = (int)(in_row1[in_x1 * components + 2] * fraction1 + \
1240 in_row1[in_x2 * components + 2] * fraction2 + \
1241 in_row2[in_x1 * components + 2] * fraction3 + \
1242 in_row2[in_x2 * components + 2] * fraction4 + 0.5); \
1245 if(components == 4) \
1246 input4 = (int)(in_row1[in_x1 * components + 3] * fraction1 + \
1247 in_row1[in_x2 * components + 3] * fraction2 + \
1248 in_row2[in_x1 * components + 3] * fraction3 + \
1249 in_row2[in_x2 * components + 3] * fraction4 + 0.5); \
1251 unsigned int opacity = (int)(master_opacity * \
1252 y_output_fraction * \
1253 x_output_fraction + 0.5); \
1254 unsigned int transparency = max - opacity; \
1256 /* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \
1258 if(components == 3) \
1260 BLEND_3(max, type); \
1264 BLEND_4(max, type); \
1270 void TranslateUnit::process_package(LoadPackage *package)
1272 TranslatePackage *pkg = (TranslatePackage*)package;
1279 // Variables for TRANSLATE
1280 VFrame *input = engine->translate_input;
1281 VFrame *output = engine->translate_output;
1282 float in_x1 = engine->translate_in_x1;
1283 float in_y1 = engine->translate_in_y1;
1284 float in_x2 = engine->translate_in_x2;
1285 float in_y2 = engine->translate_in_y2;
1286 float out_x1 = engine->translate_out_x1;
1287 float out_y1 = engine->translate_out_y1;
1288 float out_x2 = engine->translate_out_x2;
1289 float out_y2 = engine->translate_out_y2;
1290 float alpha = engine->translate_alpha;
1291 int row1 = pkg->out_row1;
1292 int row2 = pkg->out_row2;
1293 int mode = engine->translate_mode;
1294 int in_total_x = input->get_w();
1295 int in_total_y = input->get_h();
1297 (engine->translate_input->get_color_model() == BC_YUV888 ||
1298 engine->translate_input->get_color_model() == BC_YUVA8888 ||
1299 engine->translate_input->get_color_model() == BC_YUV161616 ||
1300 engine->translate_input->get_color_model() == BC_YUVA16161616);
1302 transfer_table *x_table;
1303 transfer_table *y_table;
1305 translation_array(x_table,
1314 translation_array(y_table,
1324 switch(engine->translate_input->get_color_model())
1327 TRANSLATE(0xff, unsigned char, 3, 0);
1331 TRANSLATE(0xff, unsigned char, 4, 0);
1335 TRANSLATE(0xffff, uint16_t, 3, 0);
1338 case BC_RGBA16161616:
1339 TRANSLATE(0xffff, uint16_t, 4, 0);
1343 TRANSLATE(0xff, unsigned char, 3, 1);
1347 TRANSLATE(0xff, unsigned char, 4, 1);
1351 TRANSLATE(0xffff, uint16_t, 3, 1);
1354 case BC_YUVA16161616:
1355 TRANSLATE(0xffff, uint16_t, 4, 1);
1372 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
1373 : LoadServer(cpus, cpus)
1375 this->overlay = overlay;
1378 TranslateEngine::~TranslateEngine()
1382 void TranslateEngine::init_packages()
1384 int out_y1_int = (int)translate_out_y1;
1385 int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h());
1386 int out_h = out_y2_int - out_y1_int;
1388 for(int i = 0; i < total_packages; i++)
1390 TranslatePackage *package = (TranslatePackage*)packages[i];
1391 package->out_row1 = (int)(out_y1_int + out_h /
1394 package->out_row2 = (int)((float)package->out_row1 +
1397 if(i >= total_packages - 1)
1398 package->out_row2 = out_y2_int;
1402 LoadClient* TranslateEngine::new_client()
1404 return new TranslateUnit(this, overlay);
1407 LoadPackage* TranslateEngine::new_package()
1409 return new TranslatePackage;
1419 #define SCALE_TRANSLATE(max, type, components) \
1421 int64_t opacity = (int)(alpha * max + 0.5); \
1422 int64_t transparency = max - opacity; \
1423 int out_w = out_x2 - out_x1; \
1425 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1427 int in_y = y_table[i - out_y1]; \
1428 type *in_row = (type*)in_rows[in_y] + in_x1 * components; \
1429 type *out_row = (type*)out_rows[i] + out_x1 * components; \
1431 /* X direction is scaled and requires a table lookup */ \
1432 if(out_w != in_x2 - in_x1) \
1434 for(int j = 0; j < out_w; j++) \
1436 int in_x = x_table[j]; \
1437 int input1, input2, input3, input4; \
1438 type *output = out_row + j * components; \
1440 input1 = in_row[in_x * components]; \
1441 input2 = in_row[in_x * components + 1]; \
1442 input3 = in_row[in_x * components + 2]; \
1443 if(components == 4) \
1444 input4 = in_row[in_x * components + 3]; \
1446 if(components == 3) \
1448 BLEND_3(max, type); \
1452 BLEND_4(max, type); \
1457 /* X direction is not scaled */ \
1459 for(int j = 0; j < out_w; j++) \
1461 int input1, input2, input3, input4; \
1462 type *output = out_row + j * components; \
1464 input1 = in_row[j * components]; \
1465 input2 = in_row[j * components + 1]; \
1466 input3 = in_row[j * components + 2]; \
1467 if(components == 4) \
1468 input4 = in_row[j * components + 3]; \
1470 if(components == 3) \
1472 BLEND_3(max, type); \
1476 BLEND_4(max, type); \
1485 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
1486 : LoadClient(server)
1488 this->overlay = overlay;
1489 this->scale_translate = server;
1492 ScaleTranslateUnit::~ScaleTranslateUnit()
1496 void ScaleTranslateUnit::scale_array(int* &table,
1503 float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
1505 table = new int[out_x2 - out_x1];
1509 for(int i = 0; i < out_x2 - out_x1; i++)
1511 table[i] = (int)((float)i / scale + in_x1);
1516 for(int i = 0; i < out_x2 - out_x1; i++)
1518 table[i] = (int)((float)i / scale);
1524 void ScaleTranslateUnit::process_package(LoadPackage *package)
1526 ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
1528 // Args for NEAREST_NEIGHBOR_MACRO
1529 VFrame *output = scale_translate->output;
1530 VFrame *input = scale_translate->input;
1531 int in_x1 = scale_translate->in_x1;
1532 int in_y1 = scale_translate->in_y1;
1533 int in_x2 = scale_translate->in_x2;
1534 int in_y2 = scale_translate->in_y2;
1535 int out_x1 = scale_translate->out_x1;
1536 int out_y1 = scale_translate->out_y1;
1537 int out_x2 = scale_translate->out_x2;
1538 int out_y2 = scale_translate->out_y2;
1539 float alpha = scale_translate->alpha;
1540 int mode = scale_translate->mode;
1544 unsigned char **in_rows = input->get_rows();
1545 unsigned char **out_rows = output->get_rows();
1547 scale_array(x_table,
1553 scale_array(y_table,
1561 switch(input->get_color_model())
1565 SCALE_TRANSLATE(0xff, uint8_t, 3);
1570 SCALE_TRANSLATE(0xff, uint8_t, 4);
1576 SCALE_TRANSLATE(0xffff, uint16_t, 3);
1579 case BC_RGBA16161616:
1580 case BC_YUVA16161616:
1581 SCALE_TRANSLATE(0xffff, uint16_t, 4);
1598 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
1599 : LoadServer(cpus, cpus)
1601 this->overlay = overlay;
1604 ScaleTranslateEngine::~ScaleTranslateEngine()
1608 void ScaleTranslateEngine::init_packages()
1610 int out_h = out_y2 - out_y1;
1612 for(int i = 0; i < total_packages; i++)
1614 ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i];
1615 package->out_row1 = (int)(out_y1 + out_h /
1618 package->out_row2 = (int)((float)package->out_row1 +
1621 if(i >= total_packages - 1)
1622 package->out_row2 = out_y2;
1626 LoadClient* ScaleTranslateEngine::new_client()
1628 return new ScaleTranslateUnit(this, overlay);
1631 LoadPackage* ScaleTranslateEngine::new_package()
1633 return new ScaleTranslatePackage;
1637 ScaleTranslatePackage::ScaleTranslatePackage()
1668 #define BLEND_ONLY(type, max, components) \
1670 int64_t opacity = (int)(alpha * max + 0.5); \
1671 int64_t transparency = max - opacity; \
1673 type** output_rows = (type**)output->get_rows(); \
1674 type** input_rows = (type**)input->get_rows(); \
1675 int w = input->get_w(); \
1676 int h = input->get_h(); \
1678 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1680 type* in_row = input_rows[i]; \
1681 type* output = output_rows[i]; \
1683 for(int j = 0; j < w; j++) \
1685 int input1, input2, input3, input4; \
1686 input1 = in_row[j * components]; \
1687 input2 = in_row[j * components + 1]; \
1688 input3 = in_row[j * components + 2]; \
1689 if(components == 4) input4 = in_row[j * components + 3]; \
1692 if(components == 3) \
1694 BLEND_3(max, type); \
1698 BLEND_4(max, type); \
1701 input += components; \
1702 output += components; \
1710 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
1711 : LoadClient(server)
1713 this->overlay = overlay;
1714 this->blend_engine = server;
1717 BlendUnit::~BlendUnit()
1721 void BlendUnit::process_package(LoadPackage *package)
1723 BlendPackage *pkg = (BlendPackage*)package;
1726 VFrame *output = blend_engine->output;
1727 VFrame *input = blend_engine->input;
1728 float alpha = blend_engine->alpha;
1729 int mode = blend_engine->mode;
1731 switch(input->get_color_model())
1735 BLEND_ONLY(unsigned char, 0xff, 3);
1739 BLEND_ONLY(unsigned char, 0xff, 4);
1743 BLEND_ONLY(uint16_t, 0xffff, 3);
1745 case BC_RGBA16161616:
1746 case BC_YUVA16161616:
1747 BLEND_ONLY(uint16_t, 0xffff, 4);
1754 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
1755 : LoadServer(cpus, cpus)
1757 this->overlay = overlay;
1760 BlendEngine::~BlendEngine()
1764 void BlendEngine::init_packages()
1766 for(int i = 0; i < total_packages; i++)
1768 BlendPackage *package = (BlendPackage*)packages[i];
1769 package->out_row1 = (int)(input->get_h() /
1772 package->out_row2 = (int)((float)package->out_row1 +
1776 if(i >= total_packages - 1)
1777 package->out_row2 = input->get_h();
1781 LoadClient* BlendEngine::new_client()
1783 return new BlendUnit(this, overlay);
1786 LoadPackage* BlendEngine::new_package()
1788 return new BlendPackage;
1792 BlendPackage::BlendPackage()