8 #include "overlayframe.h"
11 OverlayFrame::OverlayFrame(int cpus)
16 scaletranslate_engine = 0;
21 OverlayFrame::~OverlayFrame()
23 //printf("OverlayFrame::~OverlayFrame 1\n");
24 if(temp_frame) delete temp_frame;
25 if(scale_engine) delete scale_engine;
26 if(translate_engine) delete translate_engine;
27 if(blend_engine) delete blend_engine;
28 if(scaletranslate_engine) delete scaletranslate_engine;
29 //printf("OverlayFrame::~OverlayFrame 2\n");
41 // (255 * 255 + 0 * 0) / 255 = 255
42 // (255 * 127 + 255 * (255 - 127)) / 255 = 255
44 // (65535 * 65535 + 0 * 0) / 65535 = 65535
45 // (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535
48 // Branch prediction 4 U
50 #define BLEND_3(max, type) \
54 /* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \
57 case TRANSFER_DIVIDE: \
58 r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
59 g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
60 b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
61 r = (r * opacity + output[0] * transparency) / max; \
62 g = (g * opacity + output[1] * transparency) / max; \
63 b = (b * opacity + output[2] * transparency) / max; \
65 case TRANSFER_MULTIPLY: \
66 r = ((int64_t)input1 * output[0]) / max; \
67 g = ((int64_t)input2 * output[1]) / max; \
68 b = ((int64_t)input3 * output[2]) / max; \
69 r = (r * opacity + output[0] * transparency) / max; \
70 g = (g * opacity + output[1] * transparency) / max; \
71 b = (b * opacity + output[2] * transparency) / max; \
73 case TRANSFER_SUBTRACT: \
74 r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \
75 g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \
76 b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \
78 case TRANSFER_ADDITION: \
79 r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \
80 g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \
81 b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \
83 case TRANSFER_REPLACE: \
88 case TRANSFER_NORMAL: \
89 r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \
90 g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \
91 b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \
95 output[0] = (type)CLIP(r, 0, max); \
96 output[1] = (type)CLIP(g, 0, max); \
97 output[2] = (type)CLIP(b, 0, max); \
104 // Blending equations are drastically different for 3 and 4 components
105 #define BLEND_4(max, type) \
107 int64_t r, g, b, a; \
108 int64_t pixel_opacity, pixel_transparency; \
110 pixel_opacity = opacity * input4 / max; \
111 pixel_transparency = (max - pixel_opacity) * output[3] / max; \
115 case TRANSFER_DIVIDE: \
116 r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
117 g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
118 b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
119 r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
120 g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
121 b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
122 a = input4 > output[3] ? input4 : output[3]; \
124 case TRANSFER_MULTIPLY: \
125 r = ((int64_t)input1 * output[0]) / max; \
126 g = ((int64_t)input2 * output[1]) / max; \
127 b = ((int64_t)input3 * output[2]) / max; \
128 r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
129 g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
130 b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
131 a = input4 > output[3] ? input4 : output[3]; \
133 case TRANSFER_SUBTRACT: \
134 r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
135 g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
136 b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
137 a = input4 > output[3] ? input4 : output[3]; \
139 case TRANSFER_ADDITION: \
140 r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
141 g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
142 b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
143 a = input4 > output[3] ? input4 : output[3]; \
145 case TRANSFER_REPLACE: \
151 case TRANSFER_NORMAL: \
152 r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \
153 g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \
154 b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \
155 a = input4 > output[3] ? input4 : output[3]; \
159 output[0] = (type)CLIP(r, 0, max); \
160 output[1] = (type)CLIP(g, 0, max); \
161 output[2] = (type)CLIP(b, 0, max); \
162 output[3] = (type)a; \
172 // Bicubic algorithm using multiprocessors
173 // input -> scale nearest integer boundaries -> temp -> translation -> blend -> output
175 // Nearest neighbor algorithm using multiprocessors for blending
176 // input -> scale + translate -> blend -> output
179 int OverlayFrame::overlay(VFrame *output,
189 float alpha, // 0 - 1
191 int interpolation_type)
193 float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
194 float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
196 //printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha);
200 out_x1 += -in_x1 * w_scale;
204 if(in_x1 >= input->get_w())
206 out_x1 -= (in_x1 - input->get_w()) * w_scale;
207 in_x1 = input->get_w();
212 out_y1 += -in_y1 * h_scale;
216 if(in_y1 >= input->get_h())
218 out_y1 -= (in_y1 - input->get_h()) * h_scale;
219 in_y1 = input->get_h();
224 out_x2 += -in_x2 * w_scale;
228 if(in_x2 >= input->get_w())
230 out_x2 -= (in_x2 - input->get_w()) * w_scale;
231 in_x2 = input->get_w();
236 out_y2 += -in_y2 * h_scale;
240 if(in_y2 >= input->get_h())
242 out_y2 -= (in_y2 - input->get_h()) * h_scale;
243 in_y2 = input->get_h();
248 in_x1 += -out_x1 / w_scale;
252 if(out_x1 >= output->get_w())
254 in_x1 -= (out_x1 - output->get_w()) / w_scale;
255 out_x1 = output->get_w();
260 in_y1 += -out_y1 / h_scale;
264 if(out_y1 >= output->get_h())
266 in_y1 -= (out_y1 - output->get_h()) / h_scale;
267 out_y1 = output->get_h();
272 in_x2 += -out_x2 / w_scale;
276 if(out_x2 >= output->get_w())
278 in_x2 -= (out_x2 - output->get_w()) / w_scale;
279 out_x2 = output->get_w();
284 in_y2 += -out_y2 / h_scale;
288 if(out_y2 >= output->get_h())
290 in_y2 -= (out_y2 - output->get_h()) / h_scale;
291 out_y2 = output->get_h();
298 float in_w = in_x2 - in_x1;
299 float in_h = in_y2 - in_y1;
300 float out_w = out_x2 - out_x1;
301 float out_h = out_y2 - out_y1;
302 // Input for translation operation
303 VFrame *translation_input = input;
307 // printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1,
320 // ****************************************************************************
321 // Transfer to temp buffer by scaling nearest integer boundaries
322 // ****************************************************************************
323 if(interpolation_type != NEAREST_NEIGHBOR &&
324 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
326 // Create integer boundaries for interpolation
327 int in_x1_int = (int)in_x1;
328 int in_y1_int = (int)in_y1;
329 int in_x2_int = MIN((int)ceil(in_x2), input->get_w());
330 int in_y2_int = MIN((int)ceil(in_y2), input->get_h());
332 // Dimensions of temp frame. Integer boundaries scaled.
333 int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int));
334 int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int));
335 VFrame *scale_output;
339 #define NO_TRANSLATION1 \
340 (EQUIV(in_x1, 0) && \
342 EQUIV(out_x1, 0) && \
343 EQUIV(out_y1, 0) && \
344 EQUIV(in_x2, in_x2_int) && \
345 EQUIV(in_y2, in_y2_int) && \
346 EQUIV(out_x2, temp_w) && \
347 EQUIV(out_y2, temp_h))
351 (EQUIV(alpha, 1) && \
352 (mode == TRANSFER_REPLACE || \
353 (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
359 // Prepare destination for operation
361 // No translation and no blending. The blending operation is built into the
362 // translation unit but not the scaling unit.
364 if(NO_TRANSLATION1 &&
367 // printf("OverlayFrame::overlay input -> output\n");
369 scale_output = output;
370 translation_input = 0;
373 // If translation or blending
374 // input -> nearest integer boundary temp
377 (temp_frame->get_w() != temp_w ||
378 temp_frame->get_h() != temp_h))
386 temp_frame = new VFrame(0,
389 input->get_color_model(),
392 //printf("OverlayFrame::overlay input -> temp\n");
395 temp_frame->clear_frame();
397 // printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n",
399 scale_output = temp_frame;
400 translation_input = scale_output;
402 // Adjust input coordinates to reflect new scaled coordinates.
403 in_x1 = (in_x1 - in_x1_int) * w_scale;
404 in_y1 = (in_y1 - in_y1_int) * h_scale;
405 in_x2 = (in_x2 - in_x1_int) * w_scale;
406 in_y2 = (in_y2 - in_y1_int) * h_scale;
412 // Scale input -> scale_output
413 this->scale_output = scale_output;
414 this->scale_input = input;
415 this->w_scale = w_scale;
416 this->h_scale = h_scale;
417 this->in_x1_int = in_x1_int;
418 this->in_y1_int = in_y1_int;
419 this->out_w_int = temp_w;
420 this->out_h_int = temp_h;
421 this->interpolation_type = interpolation_type;
423 //printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int);
424 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
425 scale_engine->process_packages();
426 //printf("OverlayFrame::overlay ScaleEngine 2\n");
432 // printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
446 #define NO_TRANSLATION2 \
447 (EQUIV(in_x1, 0) && \
449 EQUIV(in_x2, translation_input->get_w()) && \
450 EQUIV(in_y2, translation_input->get_h()) && \
451 EQUIV(out_x1, 0) && \
452 EQUIV(out_y1, 0) && \
453 EQUIV(out_x2, output->get_w()) && \
454 EQUIV(out_y2, output->get_h())) \
457 (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
458 EQUIV(out_y2 - out_y1, in_y2 - in_y1))
463 //printf("OverlayFrame::overlay 4 %d\n", mode);
468 if(translation_input)
471 if( NO_TRANSLATION2 &&
475 //printf("OverlayFrame::overlay direct copy\n");
476 output->copy_from(translation_input);
480 if( NO_TRANSLATION2 &&
483 if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
486 blend_engine->output = output;
487 blend_engine->input = translation_input;
488 blend_engine->alpha = alpha;
489 blend_engine->mode = mode;
491 blend_engine->process_packages();
494 // Scale and translate using nearest neighbor
495 // Translation is exactly on integer boundaries
496 if(interpolation_type == NEAREST_NEIGHBOR ||
497 EQUIV(in_x1, (int)in_x1) &&
498 EQUIV(in_y1, (int)in_y1) &&
499 EQUIV(in_x2, (int)in_x2) &&
500 EQUIV(in_y2, (int)in_y2) &&
502 EQUIV(out_x1, (int)out_x1) &&
503 EQUIV(out_y1, (int)out_y1) &&
504 EQUIV(out_x2, (int)out_x2) &&
505 EQUIV(out_y2, (int)out_y2))
507 //printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n");
508 if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus);
511 scaletranslate_engine->output = output;
512 scaletranslate_engine->input = translation_input;
513 scaletranslate_engine->in_x1 = (int)in_x1;
514 scaletranslate_engine->in_y1 = (int)in_y1;
515 scaletranslate_engine->in_x2 = (int)in_x2;
516 scaletranslate_engine->in_y2 = (int)in_y2;
517 scaletranslate_engine->out_x1 = (int)out_x1;
518 scaletranslate_engine->out_y1 = (int)out_y1;
519 scaletranslate_engine->out_x2 = (int)out_x2;
520 scaletranslate_engine->out_y2 = (int)out_y2;
521 scaletranslate_engine->alpha = alpha;
522 scaletranslate_engine->mode = mode;
524 scaletranslate_engine->process_packages();
527 // Fractional translation
529 // Use fractional translation
530 // printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
539 this->translate_output = output;
540 this->translate_input = translation_input;
541 this->translate_in_x1 = in_x1;
542 this->translate_in_y1 = in_y1;
543 this->translate_in_x2 = in_x2;
544 this->translate_in_y2 = in_y2;
545 this->translate_out_x1 = out_x1;
546 this->translate_out_y1 = out_y1;
547 this->translate_out_x2 = out_x2;
548 this->translate_out_y2 = out_y2;
549 this->translate_alpha = alpha;
550 this->translate_mode = mode;
552 //printf("OverlayFrame::overlay 5 %d\n", mode);
553 if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
554 translate_engine->process_packages();
558 //printf("OverlayFrame::overlay 2\n");
569 ScalePackage::ScalePackage()
576 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
579 this->overlay = overlay;
582 ScaleUnit::~ScaleUnit()
588 #define BILINEAR(max, type, components) \
590 float k_y = 1.0 / scale_h; \
591 float k_x = 1.0 / scale_w; \
592 type **in_rows = (type**)input->get_rows(); \
593 type **out_rows = (type**)output->get_rows(); \
594 type zero_r, zero_g, zero_b, zero_a; \
595 int in_h_int = input->get_h(); \
596 int in_w_int = input->get_w(); \
599 zero_g = ((max + 1) >> 1) * (do_yuv); \
600 zero_b = ((max + 1) >> 1) * (do_yuv); \
601 if(components == 4) zero_a = 0; \
604 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
606 float f_y = (float)i * k_y; \
607 int i_y = (int)floor(f_y); \
608 float a = f_y - floor(f_y); \
609 type *in_row1 = in_rows[i_y + in_y1_int]; \
610 type *in_row2 = (i_y + in_y1_int < in_h_int - 1) ? \
611 in_rows[i_y + in_y1_int + 1] : \
613 type *out_row = out_rows[i]; \
615 for(int j = 0; j < out_w_int; j++) \
617 float f_x = (float)j * k_x; \
618 int i_x = (int)floor(f_x); \
619 float b = f_x - floor(f_x); \
620 int x = i_x + in_x1_int; \
621 float output1r, output1g, output1b, output1a; \
622 float output2r, output2g, output2b, output2a; \
623 float output3r, output3g, output3b, output3a; \
624 float output4r, output4g, output4b, output4a; \
626 output1r = in_row1[x * components]; \
627 output1g = in_row1[x * components + 1]; \
628 output1b = in_row1[x * components + 2]; \
629 if(components == 4) output1a = in_row1[x * components + 3]; \
631 if(x < in_w_int - 1) \
633 output2r = in_row1[x * components + components]; \
634 output2g = in_row1[x * components + components + 1]; \
635 output2b = in_row1[x * components + components + 2]; \
636 if(components == 4) output2a = in_row1[x * components + components + 3]; \
640 output4r = in_row2[x * components + components]; \
641 output4g = in_row2[x * components + components + 1]; \
642 output4b = in_row2[x * components + components + 2]; \
643 if(components == 4) output4a = in_row2[x * components + components + 3]; \
650 if(components == 4) output4a = zero_a; \
658 if(components == 4) output2a = zero_a; \
662 if(components == 4) output4a = zero_a; \
667 output3r = in_row2[x * components]; \
668 output3g = in_row2[x * components + 1]; \
669 output3b = in_row2[x * components + 2]; \
670 if(components == 4) output3a = in_row2[x * components + 3]; \
677 if(components == 4) output3a = zero_a; \
680 float anti_a = 1.0F - a; \
681 float anti_b = 1.0F - b; \
682 out_row[j * components] = \
683 (type)((anti_a) * (((anti_b) * output1r) + \
685 a * (((anti_b) * output3r) + \
687 out_row[j * components + 1] = \
688 (type)((anti_a) * (((anti_b) * output1g) + \
690 a * (((anti_b) * output3g) + \
692 out_row[j * components + 2] = \
693 (type)((anti_a) * (((anti_b) * output1b) + \
695 a * (((anti_b) * output3b) + \
697 if(components == 4) \
698 out_row[j * components + 3] = \
699 (type)((anti_a) * (((anti_b) * output1a) + \
701 a * (((anti_b) * output3a) + \
710 #define BICUBIC(max, type, components) \
712 float k_y = 1.0 / scale_h; \
713 float k_x = 1.0 / scale_w; \
714 type **in_rows = (type**)input->get_rows(); \
715 type **out_rows = (type**)output->get_rows(); \
716 float *bspline_x, *bspline_y; \
717 int in_h_int = input->get_h(); \
718 int in_w_int = input->get_w(); \
719 type zero_r, zero_g, zero_b, zero_a; \
722 zero_b = ((max + 1) >> 1) * (do_yuv); \
723 zero_g = ((max + 1) >> 1) * (do_yuv); \
724 if(components == 4) \
727 tabulate_bspline(bspline_x, \
732 tabulate_bspline(bspline_y, \
737 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
739 float f_y = (float)i * k_y; \
740 int i_y = (int)floor(f_y); \
741 float a = f_y - floor(f_y); \
744 for(int j = 0; j < out_w_int; j++) \
746 float f_x = (float)j * k_x; \
747 int i_x = (int)floor(f_x); \
748 float b = f_x - floor(f_x); \
749 float output1, output2, output3, output4; \
753 if(components == 4) \
755 int table_y = i * 4; \
758 for(int m = -1; m < 3; m++) \
760 float r1 = bspline_y[table_y++]; \
761 int y = in_y1_int + i_y + m; \
762 int table_x = j * 4; \
764 for(int n = -1; n < 3; n++) \
766 float r2 = bspline_x[table_x++]; \
767 int x = in_x1_int + i_x + n; \
768 float r_square = r1 * r2; \
770 /* Inside boundary. */ \
776 output1 += r_square * in_rows[y][x * components]; \
777 output2 += r_square * in_rows[y][x * components + 1]; \
778 output3 += r_square * in_rows[y][x * components + 2]; \
779 if(components == 4) \
780 output4 += r_square * in_rows[y][x * components + 3]; \
784 output1 += r_square * zero_r; \
785 output2 += r_square * zero_g; \
786 output3 += r_square * zero_b; \
787 if(components == 4) \
788 output4 += r_square * zero_a; \
794 out_rows[i][j * components] = (type)output1; \
795 out_rows[i][j * components + 1] = (type)output2; \
796 out_rows[i][j * components + 2] = (type)output3; \
797 if(components == 4) \
798 out_rows[i][j * components + 3] = (type)output4; \
803 delete [] bspline_x; \
804 delete [] bspline_y; \
809 // Pow function is not thread safe in Compaqt C
810 #define CUBE(x) ((x) * (x) * (x))
812 float ScaleUnit::cubic_bspline(float x)
816 if((x + 2.0F) <= 0.0F)
826 if((x + 1.0F) <= 0.0F)
844 if((x - 1.0F) <= 0.0F)
853 return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
857 void ScaleUnit::tabulate_bspline(float* &table,
862 table = new float[pixels * 4];
864 for(int i = 0, j = 0; i < pixels; i++)
866 float f_x = (float)i * scale;
867 float a = f_x - floor(f_x);
869 for(float m = -1; m < 3; m++)
871 table[j++] = cubic_bspline(coefficient * (m - a));
876 void ScaleUnit::process_package(LoadPackage *package)
878 ScalePackage *pkg = (ScalePackage*)package;
880 // Arguments for macros
881 VFrame *output = overlay->scale_output;
882 VFrame *input = overlay->scale_input;
883 float scale_w = overlay->w_scale;
884 float scale_h = overlay->h_scale;
885 int in_x1_int = overlay->in_x1_int;
886 int in_y1_int = overlay->in_y1_int;
887 int out_h_int = overlay->out_h_int;
888 int out_w_int = overlay->out_w_int;
890 (overlay->scale_input->get_color_model() == BC_YUV888 ||
891 overlay->scale_input->get_color_model() == BC_YUVA8888 ||
892 overlay->scale_input->get_color_model() == BC_YUV161616 ||
893 overlay->scale_input->get_color_model() == BC_YUVA16161616);
895 if(overlay->interpolation_type == CUBIC_CUBIC ||
896 (overlay->interpolation_type == CUBIC_LINEAR
897 && overlay->w_scale > 1 &&
898 overlay->h_scale > 1))
901 switch(overlay->scale_input->get_color_model())
905 BICUBIC(0xff, unsigned char, 3);
910 BICUBIC(0xff, unsigned char, 4);
915 BICUBIC(0xffff, uint16_t, 3);
918 case BC_RGBA16161616:
919 case BC_YUVA16161616:
920 BICUBIC(0xffff, uint16_t, 4);
925 // Perform bilinear scaling input -> scale_output
927 switch(overlay->scale_input->get_color_model())
931 BILINEAR(0xff, unsigned char, 3);
936 BILINEAR(0xff, unsigned char, 4);
941 BILINEAR(0xffff, uint16_t, 3);
944 case BC_RGBA16161616:
945 case BC_YUVA16161616:
946 BILINEAR(0xffff, uint16_t, 4);
965 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
966 : LoadServer(cpus, cpus)
968 this->overlay = overlay;
971 ScaleEngine::~ScaleEngine()
975 void ScaleEngine::init_packages()
977 for(int i = 0; i < total_packages; i++)
979 ScalePackage *package = (ScalePackage*)packages[i];
980 package->out_row1 = overlay->out_h_int / total_packages * i;
981 package->out_row2 = package->out_row1 + overlay->out_h_int / total_packages;
983 if(i >= total_packages - 1)
984 package->out_row2 = overlay->out_h_int;
988 LoadClient* ScaleEngine::new_client()
990 return new ScaleUnit(this, overlay);
993 LoadPackage* ScaleEngine::new_package()
995 return new ScalePackage;
1010 TranslatePackage::TranslatePackage()
1016 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
1017 : LoadClient(server)
1019 this->overlay = overlay;
1022 TranslateUnit::~TranslateUnit()
1028 void TranslateUnit::translation_array(transfer_table* &table,
1039 float offset = out_x1 - in_x1;
1041 out_x1_int = (int)out_x1;
1042 out_x2_int = MIN((int)ceil(out_x2), out_total);
1043 out_w_int = out_x2_int - out_x1_int;
1045 table = new transfer_table[out_w_int];
1046 bzero(table, sizeof(transfer_table) * out_w_int);
1049 //printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1052 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
1054 transfer_table *entry = &table[out_x - out_x1_int];
1056 entry->in_x1 = (int)in_x;
1057 entry->in_x2 = (int)in_x + 1;
1059 // Get fraction of output pixel to fill
1060 entry->output_fraction = 1;
1064 entry->output_fraction -= out_x1 - out_x;
1067 if(out_x2 < out_x + 1)
1069 entry->output_fraction = (out_x2 - out_x);
1072 // Advance in_x until out_x_fraction is filled
1073 float out_x_fraction = entry->output_fraction;
1074 float in_x_fraction = floor(in_x + 1) - in_x;
1076 if(out_x_fraction <= in_x_fraction)
1078 entry->in_fraction1 = out_x_fraction;
1079 entry->in_fraction2 = 0.0;
1080 in_x += out_x_fraction;
1084 entry->in_fraction1 = in_x_fraction;
1085 in_x += out_x_fraction;
1086 entry->in_fraction2 = in_x - floor(in_x);
1090 if(entry->in_x2 >= in_total)
1092 entry->in_x2 = in_total - 1;
1093 entry->in_fraction2 = 0.0;
1096 if(entry->in_x1 >= in_total)
1098 entry->in_x1 = in_total - 1;
1099 entry->in_fraction1 = 0.0;
1101 // printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n",
1105 // entry->in_fraction1,
1106 // entry->in_fraction2,
1107 // entry->output_fraction);
1144 #define TRANSLATE(max, type, components) \
1147 type **in_rows = (type**)input->get_rows(); \
1148 type **out_rows = (type**)output->get_rows(); \
1150 /* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \
1151 /* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \
1153 unsigned int master_opacity = (int)(alpha * max + 0.5); \
1154 unsigned int master_transparency = max - master_opacity; \
1156 /* printf("TRANSLATE %d\n", mode); */ \
1158 for(int i = row1; i < row2; i++) \
1160 int in_y1 = y_table[i - out_y1_int].in_x1; \
1161 int in_y2 = y_table[i - out_y1_int].in_x2; \
1162 float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \
1163 float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \
1164 float y_output_fraction = y_table[i - out_y1_int].output_fraction; \
1165 type *in_row1 = in_rows[(in_y1)]; \
1166 type *in_row2 = in_rows[(in_y2)]; \
1167 type *out_row = out_rows[i]; \
1169 for(int j = out_x1_int; j < out_x2_int; j++) \
1171 int in_x1 = x_table[j - out_x1_int].in_x1; \
1172 int in_x2 = x_table[j - out_x1_int].in_x2; \
1173 float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \
1174 float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \
1175 float x_output_fraction = x_table[j - out_x1_int].output_fraction; \
1176 type *output = &out_row[j * components]; \
1177 int input1, input2, input3, input4; \
1179 input1 = (int)(in_row1[in_x1 * components] * x_fraction1 * y_fraction1 + \
1180 in_row1[in_x2 * components] * x_fraction2 * y_fraction1 + \
1181 in_row2[in_x1 * components] * x_fraction1 * y_fraction2 + \
1182 in_row2[in_x2 * components] * x_fraction2 * y_fraction2 + 0.5); \
1183 input2 = (int)(in_row1[in_x1 * components + 1] * x_fraction1 * y_fraction1 + \
1184 in_row1[in_x2 * components + 1] * x_fraction2 * y_fraction1 + \
1185 in_row2[in_x1 * components + 1] * x_fraction1 * y_fraction2 + \
1186 in_row2[in_x2 * components + 1] * x_fraction2 * y_fraction2 + 0.5); \
1187 input3 = (int)(in_row1[in_x1 * components + 2] * x_fraction1 * y_fraction1 + \
1188 in_row1[in_x2 * components + 2] * x_fraction2 * y_fraction1 + \
1189 in_row2[in_x1 * components + 2] * x_fraction1 * y_fraction2 + \
1190 in_row2[in_x2 * components + 2] * x_fraction2 * y_fraction2 + 0.5); \
1191 if(components == 4) \
1192 input4 = (int)(in_row1[in_x1 * components + 3] * x_fraction1 * y_fraction1 + \
1193 in_row1[in_x2 * components + 3] * x_fraction2 * y_fraction1 + \
1194 in_row2[in_x1 * components + 3] * x_fraction1 * y_fraction2 + \
1195 in_row2[in_x2 * components + 3] * x_fraction2 * y_fraction2 + 0.5); \
1197 unsigned int opacity = (int)(master_opacity * \
1198 y_output_fraction * \
1199 x_output_fraction + 0.5); \
1200 unsigned int transparency = max - opacity; \
1202 /* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \
1204 if(components == 3) \
1206 BLEND_3(max, type); \
1210 BLEND_4(max, type); \
1216 void TranslateUnit::process_package(LoadPackage *package)
1218 TranslatePackage *pkg = (TranslatePackage*)package;
1225 // Variables for TRANSLATE
1226 VFrame *input = overlay->translate_input;
1227 VFrame *output = overlay->translate_output;
1228 float in_x1 = overlay->translate_in_x1;
1229 float in_y1 = overlay->translate_in_y1;
1230 float in_x2 = overlay->translate_in_x2;
1231 float in_y2 = overlay->translate_in_y2;
1232 float out_x1 = overlay->translate_out_x1;
1233 float out_y1 = overlay->translate_out_y1;
1234 float out_x2 = overlay->translate_out_x2;
1235 float out_y2 = overlay->translate_out_y2;
1236 float alpha = overlay->translate_alpha;
1237 int row1 = pkg->out_row1;
1238 int row2 = pkg->out_row2;
1239 int mode = overlay->translate_mode;
1241 transfer_table *x_table;
1242 transfer_table *y_table;
1244 translation_array(x_table,
1253 translation_array(y_table,
1263 switch(overlay->translate_input->get_color_model())
1267 TRANSLATE(0xff, unsigned char, 3);
1272 TRANSLATE(0xff, unsigned char, 4);
1277 TRANSLATE(0xffff, uint16_t, 3);
1280 case BC_RGBA16161616:
1281 case BC_YUVA16161616:
1282 TRANSLATE(0xffff, uint16_t, 4);
1299 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
1300 : LoadServer(cpus, cpus)
1302 this->overlay = overlay;
1305 TranslateEngine::~TranslateEngine()
1309 void TranslateEngine::init_packages()
1311 int out_y1_int = (int)overlay->translate_out_y1;
1312 int out_y2_int = MIN((int)ceil(overlay->translate_out_y2), overlay->translate_output->get_h());
1313 int out_h = out_y2_int - out_y1_int;
1315 for(int i = 0; i < total_packages; i++)
1317 TranslatePackage *package = (TranslatePackage*)packages[i];
1318 package->out_row1 = (int)(out_y1_int + out_h /
1321 package->out_row2 = (int)((float)package->out_row1 +
1324 if(i >= total_packages - 1)
1325 package->out_row2 = out_y2_int;
1329 LoadClient* TranslateEngine::new_client()
1331 return new TranslateUnit(this, overlay);
1334 LoadPackage* TranslateEngine::new_package()
1336 return new TranslatePackage;
1346 #define SCALE_TRANSLATE(max, type, components) \
1348 int64_t opacity = (int)(alpha * max + 0.5); \
1349 int64_t transparency = max - opacity; \
1350 int out_w = out_x2 - out_x1; \
1352 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1354 int in_y = y_table[i - out_y1]; \
1355 type *in_row = (type*)in_rows[in_y] + in_x1 * components; \
1356 type *out_row = (type*)out_rows[i] + out_x1 * components; \
1358 /* X direction is scaled and requires a table lookup */ \
1359 if(out_w != in_x2 - in_x1) \
1361 for(int j = 0; j < out_w; j++) \
1363 int in_x = x_table[j]; \
1364 int input1, input2, input3, input4; \
1365 type *output = out_row + j * components; \
1367 input1 = in_row[in_x * components]; \
1368 input2 = in_row[in_x * components + 1]; \
1369 input3 = in_row[in_x * components + 2]; \
1370 if(components == 4) \
1371 input4 = in_row[in_x * components + 3]; \
1373 if(components == 3) \
1375 BLEND_3(max, type); \
1379 BLEND_4(max, type); \
1384 /* X direction is not scaled */ \
1386 for(int j = 0; j < out_w; j++) \
1388 int input1, input2, input3, input4; \
1389 type *output = out_row + j * components; \
1391 input1 = in_row[j * components]; \
1392 input2 = in_row[j * components + 1]; \
1393 input3 = in_row[j * components + 2]; \
1394 if(components == 4) \
1395 input4 = in_row[j * components + 3]; \
1397 if(components == 3) \
1399 BLEND_3(max, type); \
1403 BLEND_4(max, type); \
1412 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
1413 : LoadClient(server)
1415 this->overlay = overlay;
1416 this->scale_translate = server;
1419 ScaleTranslateUnit::~ScaleTranslateUnit()
1423 void ScaleTranslateUnit::scale_array(int* &table,
1430 float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
1432 table = new int[out_x2 - out_x1];
1436 for(int i = 0; i < out_x2 - out_x1; i++)
1438 table[i] = (int)((float)i / scale + in_x1);
1443 for(int i = 0; i < out_x2 - out_x1; i++)
1445 table[i] = (int)((float)i / scale);
1451 void ScaleTranslateUnit::process_package(LoadPackage *package)
1453 ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
1455 // Args for NEAREST_NEIGHBOR_MACRO
1456 VFrame *output = scale_translate->output;
1457 VFrame *input = scale_translate->input;
1458 int in_x1 = scale_translate->in_x1;
1459 int in_y1 = scale_translate->in_y1;
1460 int in_x2 = scale_translate->in_x2;
1461 int in_y2 = scale_translate->in_y2;
1462 int out_x1 = scale_translate->out_x1;
1463 int out_y1 = scale_translate->out_y1;
1464 int out_x2 = scale_translate->out_x2;
1465 int out_y2 = scale_translate->out_y2;
1466 float alpha = scale_translate->alpha;
1467 int mode = scale_translate->mode;
1471 unsigned char **in_rows = input->get_rows();
1472 unsigned char **out_rows = output->get_rows();
1474 scale_array(x_table,
1480 scale_array(y_table,
1488 switch(input->get_color_model())
1492 SCALE_TRANSLATE(0xff, uint8_t, 3);
1497 SCALE_TRANSLATE(0xff, uint8_t, 4);
1503 SCALE_TRANSLATE(0xffff, uint16_t, 3);
1506 case BC_RGBA16161616:
1507 case BC_YUVA16161616:
1508 SCALE_TRANSLATE(0xffff, uint16_t, 4);
1525 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
1526 : LoadServer(cpus, cpus)
1528 this->overlay = overlay;
1531 ScaleTranslateEngine::~ScaleTranslateEngine()
1535 void ScaleTranslateEngine::init_packages()
1537 int out_h = out_y2 - out_y1;
1539 for(int i = 0; i < total_packages; i++)
1541 ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i];
1542 package->out_row1 = (int)(out_y1 + out_h /
1545 package->out_row2 = (int)((float)package->out_row1 +
1548 if(i >= total_packages - 1)
1549 package->out_row2 = out_y2;
1553 LoadClient* ScaleTranslateEngine::new_client()
1555 return new ScaleTranslateUnit(this, overlay);
1558 LoadPackage* ScaleTranslateEngine::new_package()
1560 return new ScaleTranslatePackage;
1564 ScaleTranslatePackage::ScaleTranslatePackage()
1595 #define BLEND_ONLY(type, max, components) \
1597 int64_t opacity = (int)(alpha * max + 0.5); \
1598 int64_t transparency = max - opacity; \
1600 type** output_rows = (type**)output->get_rows(); \
1601 type** input_rows = (type**)input->get_rows(); \
1602 int w = input->get_w(); \
1603 int h = input->get_h(); \
1605 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1607 type* in_row = input_rows[i]; \
1608 type* output = output_rows[i]; \
1610 for(int j = 0; j < w; j++) \
1612 int input1, input2, input3, input4; \
1613 input1 = in_row[j * components]; \
1614 input2 = in_row[j * components + 1]; \
1615 input3 = in_row[j * components + 2]; \
1616 if(components == 4) input4 = in_row[j * components + 3]; \
1619 if(components == 3) \
1621 BLEND_3(max, type); \
1625 BLEND_4(max, type); \
1628 input += components; \
1629 output += components; \
1637 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
1638 : LoadClient(server)
1640 this->overlay = overlay;
1641 this->blend_engine = server;
1644 BlendUnit::~BlendUnit()
1648 void BlendUnit::process_package(LoadPackage *package)
1650 BlendPackage *pkg = (BlendPackage*)package;
1653 VFrame *output = blend_engine->output;
1654 VFrame *input = blend_engine->input;
1655 float alpha = blend_engine->alpha;
1656 int mode = blend_engine->mode;
1658 switch(input->get_color_model())
1662 BLEND_ONLY(unsigned char, 0xff, 3);
1666 BLEND_ONLY(unsigned char, 0xff, 4);
1670 BLEND_ONLY(uint16_t, 0xffff, 3);
1672 case BC_RGBA16161616:
1673 case BC_YUVA16161616:
1674 BLEND_ONLY(uint16_t, 0xffff, 4);
1681 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
1682 : LoadServer(cpus, cpus)
1684 this->overlay = overlay;
1687 BlendEngine::~BlendEngine()
1691 void BlendEngine::init_packages()
1693 for(int i = 0; i < total_packages; i++)
1695 BlendPackage *package = (BlendPackage*)packages[i];
1696 package->out_row1 = (int)(input->get_h() /
1699 package->out_row2 = (int)((float)package->out_row1 +
1703 if(i >= total_packages - 1)
1704 package->out_row2 = input->get_h();
1708 LoadClient* BlendEngine::new_client()
1710 return new BlendUnit(this, overlay);
1713 LoadPackage* BlendEngine::new_package()
1715 return new BlendPackage;
1719 BlendPackage::BlendPackage()