10 #include "overlayframe.h"
23 OverlayFrame::OverlayFrame(int cpus)
28 scaletranslate_engine = 0;
33 OverlayFrame::~OverlayFrame()
35 //printf("OverlayFrame::~OverlayFrame 1\n");
36 if(temp_frame) delete temp_frame;
37 if(scale_engine) delete scale_engine;
38 if(translate_engine) delete translate_engine;
39 if(blend_engine) delete blend_engine;
40 if(scaletranslate_engine) delete scaletranslate_engine;
41 //printf("OverlayFrame::~OverlayFrame 2\n");
53 // (255 * 255 + 0 * 0) / 255 = 255
54 // (255 * 127 + 255 * (255 - 127)) / 255 = 255
56 // (65535 * 65535 + 0 * 0) / 65535 = 65535
57 // (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535
60 // Branch prediction 4 U
62 #define BLEND_3(max, temp_type, type, chroma_offset) \
66 /* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \
69 case TRANSFER_DIVIDE: \
70 r = output[0] ? (((temp_type)input1 * max) / output[0]) : max; \
73 g = labs((int)input2 - chroma_offset) > labs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
74 b = labs((int)input3 - chroma_offset) > labs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
78 g = output[1] ? (temp_type)input2 * max / (temp_type)output[1] : max; \
79 b = output[2] ? (temp_type)input3 * max / (temp_type)output[2] : max; \
81 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
82 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
83 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
85 case TRANSFER_MULTIPLY: \
86 r = ((temp_type)input1 * output[0]) / max; \
89 g = labs((temp_type)input2 - chroma_offset) > labs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
90 b = labs((temp_type)input3 - chroma_offset) > labs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
94 g = (temp_type)input2 * (temp_type)output[1] / max; \
95 b = (temp_type)input3 * (temp_type)output[2] / max; \
97 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
98 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
99 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
101 case TRANSFER_SUBTRACT: \
102 r = (temp_type)input1 - output[0]; \
103 g = (temp_type)input2 - ((temp_type)output[1] - chroma_offset); \
104 b = (temp_type)input3 - ((temp_type)output[2] - chroma_offset); \
105 r = (r * opacity + output[0] * transparency) / max; \
106 g = (g * opacity + output[1] * transparency) / max; \
107 b = (b * opacity + output[2] * transparency) / max; \
109 case TRANSFER_ADDITION: \
110 r = (temp_type)input1 + output[0]; \
111 g = (temp_type)input2 - chroma_offset + output[1]; \
112 b = (temp_type)input3 - chroma_offset + output[2]; \
113 r = (r * opacity + output[0] * transparency) / max; \
114 g = (g * opacity + output[1] * transparency) / max; \
115 b = (b * opacity + output[2] * transparency) / max; \
117 case TRANSFER_REPLACE: \
122 case TRANSFER_NORMAL: \
123 r = ((temp_type)input1 * opacity + output[0] * transparency) / max; \
124 g = ((temp_type)input2 * opacity + output[1] * transparency) / max; \
125 b = ((temp_type)input3 * opacity + output[2] * transparency) / max; \
129 output[0] = (type)CLIP(r, 0, max); \
130 output[1] = (type)CLIP(g, 0, max); \
131 output[2] = (type)CLIP(b, 0, max); \
138 // Blending equations are drastically different for 3 and 4 components
139 #define BLEND_4(max, temp_type, type, chroma_offset) \
141 temp_type r, g, b, a; \
142 temp_type pixel_opacity, pixel_transparency; \
143 temp_type output1 = output[0]; \
144 temp_type output2 = output[1]; \
145 temp_type output3 = output[2]; \
146 temp_type output4 = output[3]; \
148 pixel_opacity = opacity * input4; \
149 pixel_transparency = (temp_type)max * max - pixel_opacity; \
153 case TRANSFER_DIVIDE: \
154 r = output1 ? (((temp_type)input1 * max) / output1) : max; \
157 g = labs((int)input2 - chroma_offset) > labs((int)output2 - chroma_offset) ? input2 : output2; \
158 b = labs((int)input3 - chroma_offset) > labs((int)output3 - chroma_offset) ? input3 : output3; \
162 g = output2 ? (temp_type)input2 * max / (temp_type)output2 : max; \
163 b = output3 ? (temp_type)input3 * max / (temp_type)output3 : max; \
165 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
166 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
167 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
168 a = input4 > output4 ? input4 : output4; \
170 case TRANSFER_MULTIPLY: \
171 r = ((temp_type)input1 * output1) / max; \
174 g = labs((temp_type)input2 - chroma_offset) > labs((temp_type)output2 - chroma_offset) ? input2 : output2; \
175 b = labs((temp_type)input3 - chroma_offset) > labs((temp_type)output3 - chroma_offset) ? input3 : output3; \
179 g = (temp_type)input2 * (temp_type)output2 / max; \
180 b = (temp_type)input3 * (temp_type)output3 / max; \
182 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
183 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
184 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
185 a = input4 > output4 ? input4 : output4; \
187 case TRANSFER_SUBTRACT: \
188 r = (temp_type)input1 - output1; \
189 g = (temp_type)input2 - ((temp_type)output2 - chroma_offset); \
190 b = (temp_type)input3 - ((temp_type)output3 - chroma_offset); \
191 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
192 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
193 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
194 a = input4 > output4 ? input4 : output4; \
196 case TRANSFER_ADDITION: \
197 r = (temp_type)input1 + output1; \
198 g = (temp_type)input2 - chroma_offset + output2; \
199 b = (temp_type)input3 - chroma_offset + output3; \
200 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
201 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
202 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
203 a = input4 > output4 ? input4 : output4; \
205 case TRANSFER_REPLACE: \
211 case TRANSFER_NORMAL: \
212 r = (input1 * pixel_opacity + \
213 output1 * pixel_transparency) / max / max; \
214 g = ((input2 - chroma_offset) * pixel_opacity + \
215 (output2 - chroma_offset) * pixel_transparency) \
218 b = ((input3 - chroma_offset) * pixel_opacity + \
219 (output3 - chroma_offset) * pixel_transparency) \
222 a = input4 > output4 ? input4 : output4; \
226 output[0] = (type)CLIP(r, 0, max); \
227 output[1] = (type)CLIP(g, 0, max); \
228 output[2] = (type)CLIP(b, 0, max); \
229 output[3] = (type)a; \
240 // Bicubic algorithm using multiprocessors
241 // input -> scale nearest integer boundaries -> temp -> translation -> blend -> output
243 // Nearest neighbor algorithm using multiprocessors for blending
244 // input -> scale + translate -> blend -> output
247 int OverlayFrame::overlay(VFrame *output,
257 float alpha, // 0 - 1
259 int interpolation_type)
261 float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
262 float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
264 // printf("OverlayFrame::overlay 1 %f %f %f %f -> %f %f %f %f\n", in_x1,
276 out_x1 += -in_x1 * w_scale;
280 if(in_x1 >= input->get_w())
282 out_x1 -= (in_x1 - input->get_w()) * w_scale;
283 in_x1 = input->get_w();
288 out_y1 += -in_y1 * h_scale;
292 if(in_y1 >= input->get_h())
294 out_y1 -= (in_y1 - input->get_h()) * h_scale;
295 in_y1 = input->get_h();
300 out_x2 += -in_x2 * w_scale;
304 if(in_x2 >= input->get_w())
306 out_x2 -= (in_x2 - input->get_w()) * w_scale;
307 in_x2 = input->get_w();
312 out_y2 += -in_y2 * h_scale;
316 if(in_y2 >= input->get_h())
318 out_y2 -= (in_y2 - input->get_h()) * h_scale;
319 in_y2 = input->get_h();
324 in_x1 += -out_x1 / w_scale;
328 if(out_x1 >= output->get_w())
330 in_x1 -= (out_x1 - output->get_w()) / w_scale;
331 out_x1 = output->get_w();
336 in_y1 += -out_y1 / h_scale;
340 if(out_y1 >= output->get_h())
342 in_y1 -= (out_y1 - output->get_h()) / h_scale;
343 out_y1 = output->get_h();
348 in_x2 += -out_x2 / w_scale;
352 if(out_x2 >= output->get_w())
354 in_x2 -= (out_x2 - output->get_w()) / w_scale;
355 out_x2 = output->get_w();
360 in_y2 += -out_y2 / h_scale;
364 if(out_y2 >= output->get_h())
366 in_y2 -= (out_y2 - output->get_h()) / h_scale;
367 out_y2 = output->get_h();
379 float in_w = in_x2 - in_x1;
380 float in_h = in_y2 - in_y1;
381 float out_w = out_x2 - out_x1;
382 float out_h = out_y2 - out_y1;
383 // Input for translation operation
384 VFrame *translation_input = input;
387 if(in_w <= 0 || in_h <= 0 || out_w <= 0 || out_h <= 0) return 0;
390 // printf("OverlayFrame::overlay 2 %f %f %f %f -> %f %f %f %f\n", in_x1,
403 // ****************************************************************************
404 // Transfer to temp buffer by scaling nearest integer boundaries
405 // ****************************************************************************
406 if(interpolation_type != NEAREST_NEIGHBOR &&
407 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
409 // Create integer boundaries for interpolation
410 int in_x1_int = (int)in_x1;
411 int in_y1_int = (int)in_y1;
412 int in_x2_int = MIN((int)ceil(in_x2), input->get_w());
413 int in_y2_int = MIN((int)ceil(in_y2), input->get_h());
415 // Dimensions of temp frame. Integer boundaries scaled.
416 int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int));
417 int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int));
418 VFrame *scale_output;
422 #define NO_TRANSLATION1 \
423 (EQUIV(in_x1, 0) && \
425 EQUIV(out_x1, 0) && \
426 EQUIV(out_y1, 0) && \
427 EQUIV(in_x2, in_x2_int) && \
428 EQUIV(in_y2, in_y2_int) && \
429 EQUIV(out_x2, temp_w) && \
430 EQUIV(out_y2, temp_h))
434 (EQUIV(alpha, 1) && \
435 (mode == TRANSFER_REPLACE || \
436 (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
442 // Prepare destination for operation
444 // No translation and no blending. The blending operation is built into the
445 // translation unit but not the scaling unit.
447 if(NO_TRANSLATION1 &&
450 // printf("OverlayFrame::overlay input -> output\n");
452 scale_output = output;
453 translation_input = 0;
456 // If translation or blending
457 // input -> nearest integer boundary temp
460 (temp_frame->get_w() != temp_w ||
461 temp_frame->get_h() != temp_h))
469 temp_frame = new VFrame(0,
472 input->get_color_model(),
475 //printf("OverlayFrame::overlay input -> temp\n");
478 temp_frame->clear_frame();
480 // printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n",
482 scale_output = temp_frame;
483 translation_input = scale_output;
485 // Adjust input coordinates to reflect new scaled coordinates.
486 in_x1 = (in_x1 - in_x1_int) * w_scale;
487 in_y1 = (in_y1 - in_y1_int) * h_scale;
488 in_x2 = (in_x2 - in_x1_int) * w_scale;
489 in_y2 = (in_y2 - in_y1_int) * h_scale;
494 //printf("Overlay 1\n");
496 // Scale input -> scale_output
497 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
498 scale_engine->scale_output = scale_output;
499 scale_engine->scale_input = input;
500 scale_engine->w_scale = w_scale;
501 scale_engine->h_scale = h_scale;
502 scale_engine->in_x1_int = in_x1_int;
503 scale_engine->in_y1_int = in_y1_int;
504 scale_engine->out_w_int = temp_w;
505 scale_engine->out_h_int = temp_h;
506 scale_engine->interpolation_type = interpolation_type;
507 //printf("Overlay 2\n");
509 //printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int);
510 scale_engine->process_packages();
511 //printf("OverlayFrame::overlay ScaleEngine 2\n");
517 // printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
531 #define NO_TRANSLATION2 \
532 (EQUIV(in_x1, 0) && \
534 EQUIV(in_x2, translation_input->get_w()) && \
535 EQUIV(in_y2, translation_input->get_h()) && \
536 EQUIV(out_x1, 0) && \
537 EQUIV(out_y1, 0) && \
538 EQUIV(out_x2, output->get_w()) && \
539 EQUIV(out_y2, output->get_h())) \
542 (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
543 EQUIV(out_y2 - out_y1, in_y2 - in_y1))
548 //printf("OverlayFrame::overlay 4 %d\n", mode);
553 if(translation_input)
556 if( NO_TRANSLATION2 &&
560 //printf("OverlayFrame::overlay direct copy\n");
561 output->copy_from(translation_input);
565 if( NO_TRANSLATION2 &&
568 if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
571 blend_engine->output = output;
572 blend_engine->input = translation_input;
573 blend_engine->alpha = alpha;
574 blend_engine->mode = mode;
576 blend_engine->process_packages();
579 // Scale and translate using nearest neighbor
580 // Translation is exactly on integer boundaries
581 if(interpolation_type == NEAREST_NEIGHBOR ||
582 EQUIV(in_x1, (int)in_x1) &&
583 EQUIV(in_y1, (int)in_y1) &&
584 EQUIV(in_x2, (int)in_x2) &&
585 EQUIV(in_y2, (int)in_y2) &&
587 EQUIV(out_x1, (int)out_x1) &&
588 EQUIV(out_y1, (int)out_y1) &&
589 EQUIV(out_x2, (int)out_x2) &&
590 EQUIV(out_y2, (int)out_y2))
592 //printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n");
593 if(!scaletranslate_engine) scaletranslate_engine =
594 new ScaleTranslateEngine(this, cpus);
597 scaletranslate_engine->output = output;
598 scaletranslate_engine->input = translation_input;
599 scaletranslate_engine->in_x1 = (int)in_x1;
600 scaletranslate_engine->in_y1 = (int)in_y1;
601 scaletranslate_engine->in_x2 = (int)in_x2;
602 scaletranslate_engine->in_y2 = (int)in_y2;
603 scaletranslate_engine->out_x1 = (int)out_x1;
604 scaletranslate_engine->out_y1 = (int)out_y1;
605 scaletranslate_engine->out_x2 = (int)out_x2;
606 scaletranslate_engine->out_y2 = (int)out_y2;
607 scaletranslate_engine->alpha = alpha;
608 scaletranslate_engine->mode = mode;
610 scaletranslate_engine->process_packages();
613 // Fractional translation
615 // Use fractional translation
616 // printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",
626 //printf("Overlay 3\n");
627 if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
628 translate_engine->translate_output = output;
629 translate_engine->translate_input = translation_input;
630 translate_engine->translate_in_x1 = in_x1;
631 translate_engine->translate_in_y1 = in_y1;
632 translate_engine->translate_in_x2 = in_x2;
633 translate_engine->translate_in_y2 = in_y2;
634 translate_engine->translate_out_x1 = out_x1;
635 translate_engine->translate_out_y1 = out_y1;
636 translate_engine->translate_out_x2 = out_x2;
637 translate_engine->translate_out_y2 = out_y2;
638 translate_engine->translate_alpha = alpha;
639 translate_engine->translate_mode = mode;
640 //printf("Overlay 4\n");
642 //printf("OverlayFrame::overlay 5 %d\n", mode);
643 translate_engine->process_packages();
647 //printf("OverlayFrame::overlay 2\n");
658 ScalePackage::ScalePackage()
665 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
668 this->overlay = overlay;
669 this->engine = server;
672 ScaleUnit::~ScaleUnit()
678 void ScaleUnit::tabulate_reduction(bilinear_table_t* &table,
684 table = new bilinear_table_t[out_total];
685 bzero(table, sizeof(bilinear_table_t) * out_total);
686 //printf("ScaleUnit::tabulate_reduction 1 %f %d %d %d\n", scale, in_pixel1, out_total, in_total);
687 for(int i = 0; i < out_total; i++)
690 float in_start = out_start * scale;
691 float out_end = i + 1;
692 float in_end = out_end * scale;
693 bilinear_table_t *entry = table + i;
694 //printf("ScaleUnit::tabulate_reduction 1 %f %f %f %f\n", out_start, out_end, in_start, in_end);
696 // Store input fraction
697 entry->input_fraction1 = (floor(in_start + 1) - in_start) / scale;
698 entry->input_fraction2 = 1.0 / scale;
699 entry->input_fraction3 = (in_end - floor(in_end)) / scale;
701 if(in_end >= in_total - in_pixel1)
703 in_end = in_total - in_pixel1 - 1;
705 int difference = (int)in_end - (int)in_start - 1;
706 if(difference < 0) difference = 0;
707 entry->input_fraction3 = 1.0 -
708 entry->input_fraction1 -
709 entry->input_fraction2 * difference;
712 // Store input pixels
713 entry->input_pixel1 = (int)in_start;
714 entry->input_pixel2 = (int)in_end;
716 // printf("ScaleUnit::tabulate_reduction 1 %d %d %f %f %f\n",
717 // entry->input_pixel1,
718 // entry->input_pixel2,
719 // entry->input_fraction1,
720 // entry->input_fraction2,
721 // entry->input_fraction3);
725 if(entry->input_pixel1 > entry->input_pixel2)
727 entry->input_pixel1 = entry->input_pixel2;
728 entry->input_fraction1 = 0;
731 // Get total fraction of output pixel used
732 // if(entry->input_pixel2 > entry->input_pixel1)
733 entry->total_fraction =
734 entry->input_fraction1 +
735 entry->input_fraction2 * (entry->input_pixel2 - entry->input_pixel1 - 1) +
736 entry->input_fraction3;
737 entry->input_pixel1 += in_pixel1;
738 entry->input_pixel2 += in_pixel1;
742 void ScaleUnit::tabulate_enlarge(bilinear_table_t* &table,
748 table = new bilinear_table_t[out_total];
749 bzero(table, sizeof(bilinear_table_t) * out_total);
751 for(int i = 0; i < out_total; i++)
753 bilinear_table_t *entry = table + i;
754 float in_pixel = i * scale;
755 entry->input_pixel1 = (int)floor(in_pixel);
756 entry->input_pixel2 = entry->input_pixel1 + 1;
758 if(in_pixel <= in_total)
760 entry->input_fraction3 = in_pixel - entry->input_pixel1;
764 entry->input_fraction3 = 0;
765 entry->input_pixel2 = 0;
770 entry->input_fraction1 = entry->input_pixel2 - in_pixel;
774 entry->input_fraction1 = 0;
775 entry->input_pixel1 = 0;
778 if(entry->input_pixel2 >= in_total - in_pixel1)
780 entry->input_pixel2 = entry->input_pixel1;
781 entry->input_fraction3 = 1.0 - entry->input_fraction1;
784 entry->total_fraction =
785 entry->input_fraction1 +
786 entry->input_fraction3;
787 entry->input_pixel1 += in_pixel1;
788 entry->input_pixel2 += in_pixel1;
790 // printf("ScaleUnit::tabulate_enlarge %d %d %f %f %f\n",
791 // entry->input_pixel1,
792 // entry->input_pixel2,
793 // entry->input_fraction1,
794 // entry->input_fraction2,
795 // entry->input_fraction3);
799 void ScaleUnit::dump_bilinear(bilinear_table_t *table, int total)
801 printf("ScaleUnit::dump_bilinear\n");
802 for(int i = 0; i < total; i++)
804 printf("out=%d inpixel1=%d inpixel2=%d infrac1=%f infrac2=%f infrac3=%f total=%f\n",
806 table[i].input_pixel1,
807 table[i].input_pixel2,
808 table[i].input_fraction1,
809 table[i].input_fraction2,
810 table[i].input_fraction3,
811 table[i].total_fraction);
815 #define PIXEL_REDUCE_MACRO(type, components, row) \
817 type *input_row = &in_rows[row][x_entry->input_pixel1 * components]; \
818 type *input_end = &in_rows[row][x_entry->input_pixel2 * components]; \
820 /* Do first pixel */ \
821 temp_f1 += input_scale1 * input_row[0]; \
822 temp_f2 += input_scale1 * input_row[1]; \
823 temp_f3 += input_scale1 * input_row[2]; \
824 if(components == 4) temp_f4 += input_scale1 * input_row[3]; \
826 /* Do last pixel */ \
827 /* if(input_row < input_end) */\
829 temp_f1 += input_scale3 * input_end[0]; \
830 temp_f2 += input_scale3 * input_end[1]; \
831 temp_f3 += input_scale3 * input_end[2]; \
832 if(components == 4) temp_f4 += input_scale3 * input_end[3]; \
835 /* Do middle pixels */ \
836 for(input_row += components; input_row < input_end; input_row += components) \
838 temp_f1 += input_scale2 * input_row[0]; \
839 temp_f2 += input_scale2 * input_row[1]; \
840 temp_f3 += input_scale2 * input_row[2]; \
841 if(components == 4) temp_f4 += input_scale2 * input_row[3]; \
845 // Bilinear reduction and suboptimal enlargement.
846 // Very high quality.
847 #define BILINEAR_REDUCE(max, type, components) \
849 bilinear_table_t *x_table, *y_table; \
850 int out_h = pkg->out_row2 - pkg->out_row1; \
851 type **in_rows = (type**)input->get_rows(); \
852 type **out_rows = (type**)output->get_rows(); \
855 tabulate_reduction(x_table, \
861 tabulate_enlarge(x_table, \
868 tabulate_reduction(y_table, \
874 tabulate_enlarge(y_table, \
879 /* dump_bilinear(y_table, out_h_int); */\
881 for(int i = 0; i < out_h; i++) \
883 type *out_row = out_rows[i + pkg->out_row1]; \
884 bilinear_table_t *y_entry = &y_table[i + pkg->out_row1]; \
885 /*printf("BILINEAR_REDUCE 2 %d %d %d\n", i, y_entry->input_pixel1, y_entry->input_pixel2); */\
887 for(int j = 0; j < out_w_int; j++) \
889 bilinear_table_t *x_entry = &x_table[j]; \
890 /* Load rounding factors */ \
891 float temp_f1 = .5; \
892 float temp_f2 = .5; \
893 float temp_f3 = .5; \
894 float temp_f4 = .5; \
897 float input_scale1 = y_entry->input_fraction1 * x_entry->input_fraction1; \
898 float input_scale2 = y_entry->input_fraction1 * x_entry->input_fraction2; \
899 float input_scale3 = y_entry->input_fraction1 * x_entry->input_fraction3; \
900 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel1) \
905 input_scale1 = y_entry->input_fraction3 * x_entry->input_fraction1; \
906 input_scale2 = y_entry->input_fraction3 * x_entry->input_fraction2; \
907 input_scale3 = y_entry->input_fraction3 * x_entry->input_fraction3; \
908 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel2) \
913 input_scale1 = y_entry->input_fraction2 * x_entry->input_fraction1; \
914 input_scale2 = y_entry->input_fraction2 * x_entry->input_fraction2; \
915 input_scale3 = y_entry->input_fraction2 * x_entry->input_fraction3; \
916 for(int k = y_entry->input_pixel1 + 1; \
917 k < y_entry->input_pixel2; \
920 PIXEL_REDUCE_MACRO(type, components, k) \
925 if(temp_f1 > max) temp_f1 = max; \
926 if(temp_f2 > max) temp_f2 = max; \
927 if(temp_f3 > max) temp_f3 = max; \
928 if(components == 4) if(temp_f4 > max) temp_f4 = max; \
929 out_row[j * components ] = (type)temp_f1; \
930 out_row[j * components + 1] = (type)temp_f2; \
931 out_row[j * components + 2] = (type)temp_f3; \
932 if(components == 4) out_row[j * components + 3] = (type)temp_f4; \
934 /*printf("BILINEAR_REDUCE 3 %d\n", i);*/ \
943 // Only 2 input pixels
944 #define BILINEAR_ENLARGE(max, type, components) \
946 /*printf("BILINEAR_ENLARGE 1\n");*/ \
947 float k_y = 1.0 / scale_h; \
948 float k_x = 1.0 / scale_w; \
949 type **in_rows = (type**)input->get_rows(); \
950 type **out_rows = (type**)output->get_rows(); \
951 int out_h = pkg->out_row2 - pkg->out_row1; \
952 int in_h_int = input->get_h(); \
953 int in_w_int = input->get_w(); \
954 int *table_int_x1, *table_int_y1; \
955 int *table_int_x2, *table_int_y2; \
956 float *table_frac_x_f, *table_antifrac_x_f, *table_frac_y_f, *table_antifrac_y_f; \
957 int *table_frac_x_i, *table_antifrac_x_i, *table_frac_y_i, *table_antifrac_y_i; \
961 tabulate_blinear_f(table_int_x1, \
964 table_antifrac_x_f, \
970 tabulate_blinear_f(table_int_y1, \
973 table_antifrac_y_f, \
982 tabulate_blinear_i(table_int_x1, \
985 table_antifrac_x_i, \
991 tabulate_blinear_i(table_int_y1, \
994 table_antifrac_y_i, \
1002 for(int i = 0; i < out_h; i++) \
1004 int i_y1 = table_int_y1[i]; \
1005 int i_y2 = table_int_y2[i]; \
1009 uint64_t anti_a_i; \
1012 a_f = table_frac_y_f[i]; \
1013 anti_a_f = table_antifrac_y_f[i]; \
1017 a_i = table_frac_y_i[i]; \
1018 anti_a_i = table_antifrac_y_i[i]; \
1020 type *in_row1 = in_rows[i_y1]; \
1021 type *in_row2 = in_rows[i_y2]; \
1022 type *out_row = out_rows[i + pkg->out_row1]; \
1024 for(int j = 0; j < out_w_int; j++) \
1026 int i_x1 = table_int_x1[j]; \
1027 int i_x2 = table_int_x2[j]; \
1030 float output1r, output1g, output1b, output1a; \
1031 float output2r, output2g, output2b, output2a; \
1032 float output3r, output3g, output3b, output3a; \
1033 float output4r, output4g, output4b, output4a; \
1036 b_f = table_frac_x_f[j]; \
1037 anti_b_f = table_antifrac_x_f[j]; \
1039 output1r = in_row1[i_x1 * components]; \
1040 output1g = in_row1[i_x1 * components + 1]; \
1041 output1b = in_row1[i_x1 * components + 2]; \
1042 if(components == 4) output1a = in_row1[i_x1 * components + 3]; \
1044 output2r = in_row1[i_x2 * components]; \
1045 output2g = in_row1[i_x2 * components + 1]; \
1046 output2b = in_row1[i_x2 * components + 2]; \
1047 if(components == 4) output2a = in_row1[i_x2 * components + 3]; \
1049 output3r = in_row2[i_x1 * components]; \
1050 output3g = in_row2[i_x1 * components + 1]; \
1051 output3b = in_row2[i_x1 * components + 2]; \
1052 if(components == 4) output3a = in_row2[i_x1 * components + 3]; \
1054 output4r = in_row2[i_x2 * components]; \
1055 output4g = in_row2[i_x2 * components + 1]; \
1056 output4b = in_row2[i_x2 * components + 2]; \
1057 if(components == 4) output4a = in_row2[i_x2 * components + 3]; \
1059 out_row[j * components] = \
1060 (type)(anti_a_f * (anti_b_f * output1r + \
1062 a_f * (anti_b_f * output3r + \
1064 out_row[j * components + 1] = \
1065 (type)(anti_a_f * (anti_b_f * output1g + \
1067 a_f * ((anti_b_f * output3g) + \
1069 out_row[j * components + 2] = \
1070 (type)(anti_a_f * ((anti_b_f * output1b) + \
1071 (b_f * output2b)) + \
1072 a_f * ((anti_b_f * output3b) + \
1074 if(components == 4) \
1075 out_row[j * components + 3] = \
1076 (type)(anti_a_f * ((anti_b_f * output1a) + \
1077 (b_f * output2a)) + \
1078 a_f * ((anti_b_f * output3a) + \
1083 uint64_t output1r, output1g, output1b, output1a; \
1084 uint64_t output2r, output2g, output2b, output2a; \
1085 uint64_t output3r, output3g, output3b, output3a; \
1086 uint64_t output4r, output4g, output4b, output4a; \
1088 uint64_t anti_b_i; \
1089 b_i = table_frac_x_i[j]; \
1090 anti_b_i = table_antifrac_x_i[j]; \
1092 output1r = in_row1[i_x1 * components]; \
1093 output1g = in_row1[i_x1 * components + 1]; \
1094 output1b = in_row1[i_x1 * components + 2]; \
1095 if(components == 4) output1a = in_row1[i_x1 * components + 3]; \
1097 output2r = in_row1[i_x2 * components]; \
1098 output2g = in_row1[i_x2 * components + 1]; \
1099 output2b = in_row1[i_x2 * components + 2]; \
1100 if(components == 4) output2a = in_row1[i_x2 * components + 3]; \
1102 output3r = in_row2[i_x1 * components]; \
1103 output3g = in_row2[i_x1 * components + 1]; \
1104 output3b = in_row2[i_x1 * components + 2]; \
1105 if(components == 4) output3a = in_row2[i_x1 * components + 3]; \
1107 output4r = in_row2[i_x2 * components]; \
1108 output4g = in_row2[i_x2 * components + 1]; \
1109 output4b = in_row2[i_x2 * components + 2]; \
1110 if(components == 4) output4a = in_row2[i_x2 * components + 3]; \
1112 out_row[j * components] = \
1113 (type)((anti_a_i * (anti_b_i * output1r + \
1115 a_i * (anti_b_i * output3r + \
1116 b_i * output4r)) / 0xffffffff); \
1117 out_row[j * components + 1] = \
1118 (type)((anti_a_i * (anti_b_i * output1g + \
1120 a_i * (anti_b_i * output3g + \
1121 b_i * output4g)) / 0xffffffff); \
1122 out_row[j * components + 2] = \
1123 (type)((anti_a_i * (anti_b_i * output1b + \
1125 a_i * (anti_b_i * output3b + \
1126 b_i * output4b)) / 0xffffffff); \
1127 if(components == 4) \
1128 out_row[j * components + 3] = \
1129 (type)((anti_a_i * (anti_b_i * output1a + \
1131 a_i * (anti_b_i * output3a + \
1132 b_i * output4a)) / 0xffffffff); \
1138 delete [] table_int_x1; \
1139 delete [] table_int_x2; \
1140 delete [] table_int_y1; \
1141 delete [] table_int_y2; \
1144 delete [] table_frac_x_f; \
1145 delete [] table_antifrac_x_f; \
1146 delete [] table_frac_y_f; \
1147 delete [] table_antifrac_y_f; \
1151 delete [] table_frac_x_i; \
1152 delete [] table_antifrac_x_i; \
1153 delete [] table_frac_y_i; \
1154 delete [] table_antifrac_y_i; \
1157 /*printf("BILINEAR_ENLARGE 2\n");*/ \
1161 #define BICUBIC(max, type, components) \
1163 float k_y = 1.0 / scale_h; \
1164 float k_x = 1.0 / scale_w; \
1165 type **in_rows = (type**)input->get_rows(); \
1166 type **out_rows = (type**)output->get_rows(); \
1167 float *bspline_x_f, *bspline_y_f; \
1168 int *bspline_x_i, *bspline_y_i; \
1169 int *in_x_table, *in_y_table; \
1170 int in_h_int = input->get_h(); \
1171 int in_w_int = input->get_w(); \
1175 tabulate_bcubic_f(bspline_x_f, \
1183 tabulate_bcubic_f(bspline_y_f, \
1193 tabulate_bcubic_i(bspline_x_i, \
1201 tabulate_bcubic_i(bspline_y_i, \
1210 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1212 for(int j = 0; j < out_w_int; j++) \
1214 int i_x = (int)(k_x * j); \
1215 float output1_f, output2_f, output3_f, output4_f; \
1216 uint64_t output1_i, output2_i, output3_i, output4_i; \
1222 if(components == 4) \
1230 if(components == 4) \
1233 int table_y = i * 4; \
1236 for(int m = -1; m < 3; m++) \
1241 r1_f = bspline_y_f[table_y]; \
1243 r1_i = bspline_y_i[table_y]; \
1244 int y = in_y_table[table_y]; \
1245 int table_x = j * 4; \
1247 for(int n = -1; n < 3; n++) \
1252 r2_f = bspline_x_f[table_x]; \
1254 r2_i = bspline_x_i[table_x]; \
1255 int x = in_x_table[table_x]; \
1257 uint64_t r_square_i; \
1260 r_square_f = r1_f * r2_f; \
1261 output1_f += r_square_f * in_rows[y][x * components]; \
1262 output2_f += r_square_f * in_rows[y][x * components + 1]; \
1263 output3_f += r_square_f * in_rows[y][x * components + 2]; \
1264 if(components == 4) \
1265 output4_f += r_square_f * in_rows[y][x * components + 3]; \
1269 r_square_i = r1_i * r2_i; \
1270 output1_i += r_square_i * in_rows[y][x * components]; \
1271 output2_i += r_square_i * in_rows[y][x * components + 1]; \
1272 output3_i += r_square_i * in_rows[y][x * components + 2]; \
1273 if(components == 4) \
1274 output4_i += r_square_i * in_rows[y][x * components + 3]; \
1285 out_rows[i][j * components] = (type)output1_f; \
1286 out_rows[i][j * components + 1] = (type)output2_f; \
1287 out_rows[i][j * components + 2] = (type)output3_f; \
1288 if(components == 4) \
1289 out_rows[i][j * components + 3] = (type)output4_f; \
1293 out_rows[i][j * components] = (type)(output1_i / 0xffffffff); \
1294 out_rows[i][j * components + 1] = (type)(output2_i / 0xffffffff); \
1295 out_rows[i][j * components + 2] = (type)(output3_i / 0xffffffff); \
1296 if(components == 4) \
1297 out_rows[i][j * components + 3] = (type)(output4_i / 0xffffffff); \
1305 delete [] bspline_x_f; \
1306 delete [] bspline_y_f; \
1310 delete [] bspline_x_i; \
1311 delete [] bspline_y_i; \
1313 delete [] in_x_table; \
1314 delete [] in_y_table; \
1320 // Pow function is not thread safe in Compaqt C
1321 #define CUBE(x) ((x) * (x) * (x))
1323 float ScaleUnit::cubic_bspline(float x)
1327 if((x + 2.0F) <= 0.0F)
1337 if((x + 1.0F) <= 0.0F)
1355 if((x - 1.0F) <= 0.0F)
1365 return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
1369 void ScaleUnit::tabulate_bcubic_f(float* &coef_table,
1377 coef_table = new float[pixels * 4];
1378 coord_table = new int[pixels * 4];
1379 for(int i = 0, j = 0; i < pixels; i++)
1381 float f_x = (float)i * scale;
1382 float a = f_x - floor(f_x);
1384 for(float m = -1; m < 3; m++)
1386 coef_table[j] = cubic_bspline(coefficient * (m - a));
1387 coord_table[j] = (int)(start + (int)f_x + m);
1388 CLAMP(coord_table[j], 0, total_pixels - 1);
1395 void ScaleUnit::tabulate_bcubic_i(int* &coef_table,
1403 coef_table = new int[pixels * 4];
1404 coord_table = new int[pixels * 4];
1405 for(int i = 0, j = 0; i < pixels; i++)
1407 float f_x = (float)i * scale;
1408 float a = f_x - floor(f_x);
1410 for(float m = -1; m < 3; m++)
1412 coef_table[j] = (int)(cubic_bspline(coefficient * (m - a)) * 0x10000);
1413 coord_table[j] = (int)(start + (int)f_x + m);
1414 CLAMP(coord_table[j], 0, total_pixels - 1);
1421 void ScaleUnit::tabulate_blinear_f(int* &table_int1,
1424 float* &table_antifrac,
1431 table_int1 = new int[pixel2 - pixel1];
1432 table_int2 = new int[pixel2 - pixel1];
1433 table_frac = new float[pixel2 - pixel1];
1434 table_antifrac = new float[pixel2 - pixel1];
1436 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
1438 float f_x = (float)i * scale;
1439 int i_x = (int)floor(f_x);
1440 float a = (f_x - floor(f_x));
1442 table_int1[j] = i_x + start;
1443 table_int2[j] = i_x + start + 1;
1444 CLAMP(table_int1[j], 0, total_pixels - 1);
1445 CLAMP(table_int2[j], 0, total_pixels - 1);
1447 table_antifrac[j] = 1.0F - a;
1448 //printf("ScaleUnit::tabulate_blinear %d %d %d\n", j, table_int1[j], table_int2[j]);
1452 void ScaleUnit::tabulate_blinear_i(int* &table_int1,
1455 int* &table_antifrac,
1462 table_int1 = new int[pixel2 - pixel1];
1463 table_int2 = new int[pixel2 - pixel1];
1464 table_frac = new int[pixel2 - pixel1];
1465 table_antifrac = new int[pixel2 - pixel1];
1467 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
1469 double f_x = (float)i * scale;
1470 int i_x = (int)floor(f_x);
1471 float a = (f_x - floor(f_x));
1473 table_int1[j] = i_x + start;
1474 table_int2[j] = i_x + start + 1;
1475 CLAMP(table_int1[j], 0, total_pixels - 1);
1476 CLAMP(table_int2[j], 0, total_pixels - 1);
1477 table_frac[j] = (int)(a * 0xffff);
1478 table_antifrac[j] = (int)((1.0F - a) * 0x10000);
1479 //printf("ScaleUnit::tabulate_blinear %d %d %d\n", j, table_int1[j], table_int2[j]);
1483 void ScaleUnit::process_package(LoadPackage *package)
1485 ScalePackage *pkg = (ScalePackage*)package;
1487 //printf("ScaleUnit::process_package 1\n");
1488 // Arguments for macros
1489 VFrame *output = engine->scale_output;
1490 VFrame *input = engine->scale_input;
1491 float scale_w = engine->w_scale;
1492 float scale_h = engine->h_scale;
1493 int in_x1_int = engine->in_x1_int;
1494 int in_y1_int = engine->in_y1_int;
1495 int out_h_int = engine->out_h_int;
1496 int out_w_int = engine->out_w_int;
1498 (input->get_color_model() == BC_YUV888 ||
1499 input->get_color_model() == BC_YUVA8888 ||
1500 input->get_color_model() == BC_YUV161616 ||
1501 input->get_color_model() == BC_YUVA16161616);
1503 //printf("ScaleUnit::process_package 2 %f %f\n", engine->w_scale, engine->h_scale);
1504 if(engine->interpolation_type == CUBIC_CUBIC ||
1505 (engine->interpolation_type == CUBIC_LINEAR
1506 && engine->w_scale > 1 &&
1507 engine->h_scale > 1))
1510 switch(engine->scale_input->get_color_model())
1514 BICUBIC(0xff, unsigned char, 3);
1519 BICUBIC(0xff, unsigned char, 4);
1524 BICUBIC(0xffff, uint16_t, 3);
1527 case BC_RGBA16161616:
1528 case BC_YUVA16161616:
1529 BICUBIC(0xffff, uint16_t, 4);
1534 if(engine->w_scale > 1 &&
1535 engine->h_scale > 1)
1537 // Perform bilinear scaling input -> scale_output
1539 switch(engine->scale_input->get_color_model())
1543 BILINEAR_ENLARGE(0xff, unsigned char, 3);
1548 BILINEAR_ENLARGE(0xff, unsigned char, 4);
1553 BILINEAR_ENLARGE(0xffff, uint16_t, 3);
1556 case BC_RGBA16161616:
1557 case BC_YUVA16161616:
1558 BILINEAR_ENLARGE(0xffff, uint16_t, 4);
1564 switch(engine->scale_input->get_color_model())
1568 BILINEAR_REDUCE(0xff, unsigned char, 3);
1573 BILINEAR_REDUCE(0xff, unsigned char, 4);
1578 BILINEAR_REDUCE(0xffff, uint16_t, 3);
1581 case BC_RGBA16161616:
1582 case BC_YUVA16161616:
1583 BILINEAR_REDUCE(0xffff, uint16_t, 4);
1587 //printf("ScaleUnit::process_package 3\n");
1603 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
1604 : LoadServer(cpus, cpus)
1606 this->overlay = overlay;
1609 ScaleEngine::~ScaleEngine()
1613 void ScaleEngine::init_packages()
1615 for(int i = 0; i < total_packages; i++)
1617 ScalePackage *package = (ScalePackage*)packages[i];
1618 package->out_row1 = out_h_int / total_packages * i;
1619 package->out_row2 = package->out_row1 + out_h_int / total_packages;
1621 if(i >= total_packages - 1)
1622 package->out_row2 = out_h_int;
1626 LoadClient* ScaleEngine::new_client()
1628 return new ScaleUnit(this, overlay);
1631 LoadPackage* ScaleEngine::new_package()
1633 return new ScalePackage;
1648 TranslatePackage::TranslatePackage()
1654 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
1655 : LoadClient(server)
1657 this->overlay = overlay;
1658 this->engine = server;
1661 TranslateUnit::~TranslateUnit()
1667 void TranslateUnit::translation_array_f(transfer_table_f* &table,
1678 float offset = out_x1 - in_x1;
1679 //printf("OverlayFrame::translation_array_f 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1681 out_x1_int = (int)out_x1;
1682 out_x2_int = MIN((int)ceil(out_x2), out_total);
1683 out_w_int = out_x2_int - out_x1_int;
1685 table = new transfer_table_f[out_w_int];
1686 bzero(table, sizeof(transfer_table_f) * out_w_int);
1689 //printf("OverlayFrame::translation_array_f 2 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1692 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
1694 transfer_table_f *entry = &table[out_x - out_x1_int];
1696 entry->in_x1 = (int)in_x;
1697 entry->in_x2 = (int)in_x + 1;
1699 // Get fraction of output pixel to fill
1700 entry->output_fraction = 1;
1704 entry->output_fraction -= out_x1 - out_x;
1707 if(out_x2 < out_x + 1)
1709 entry->output_fraction = (out_x2 - out_x);
1712 // Advance in_x until out_x_fraction is filled
1713 float out_x_fraction = entry->output_fraction;
1714 float in_x_fraction = floor(in_x + 1) - in_x;
1716 if(out_x_fraction <= in_x_fraction)
1718 entry->in_fraction1 = out_x_fraction;
1719 entry->in_fraction2 = 0.0;
1720 in_x += out_x_fraction;
1724 entry->in_fraction1 = in_x_fraction;
1725 in_x += out_x_fraction;
1726 entry->in_fraction2 = in_x - floor(in_x);
1729 // Clip in_x and zero out fraction. This doesn't work for YUV.
1730 if(entry->in_x2 >= in_total)
1732 entry->in_x2 = in_total - 1;
1733 entry->in_fraction2 = 0.0;
1736 if(entry->in_x1 >= in_total)
1738 entry->in_x1 = in_total - 1;
1739 entry->in_fraction1 = 0.0;
1741 // printf("OverlayFrame::translation_array_f 2 %d %d %d %f %f %f\n",
1745 // entry->in_fraction1,
1746 // entry->in_fraction2,
1747 // entry->output_fraction);
1752 void TranslateUnit::translation_array_i(transfer_table_i* &table,
1763 float offset = out_x1 - in_x1;
1765 out_x1_int = (int)out_x1;
1766 out_x2_int = MIN((int)ceil(out_x2), out_total);
1767 out_w_int = out_x2_int - out_x1_int;
1769 table = new transfer_table_i[out_w_int];
1770 bzero(table, sizeof(transfer_table_i) * out_w_int);
1773 //printf("OverlayFrame::translation_array_f 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1776 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
1778 transfer_table_i *entry = &table[out_x - out_x1_int];
1780 entry->in_x1 = (int)in_x;
1781 entry->in_x2 = (int)in_x + 1;
1783 // Get fraction of output pixel to fill
1784 entry->output_fraction = 0x10000;
1788 entry->output_fraction -= (int)((out_x1 - out_x) * 0x10000);
1791 if(out_x2 < out_x + 1)
1793 entry->output_fraction = (int)((out_x2 - out_x) * 0x10000);
1796 // Advance in_x until out_x_fraction is filled
1797 int out_x_fraction = entry->output_fraction;
1798 int in_x_fraction = (int)((floor(in_x + 1) - in_x) * 0x10000);
1800 if(out_x_fraction <= in_x_fraction)
1802 entry->in_fraction1 = out_x_fraction;
1803 entry->in_fraction2 = 0;
1804 in_x += (float)out_x_fraction / 0x10000;
1808 entry->in_fraction1 = in_x_fraction;
1809 in_x += (float)out_x_fraction / 0x10000;
1810 entry->in_fraction2 = (int)((in_x - floor(in_x)) * 0x10000);
1813 // Clip in_x and zero out fraction. This doesn't work for YUV.
1814 if(entry->in_x2 >= in_total)
1816 entry->in_x2 = in_total - 1;
1817 entry->in_fraction2 = 0;
1820 if(entry->in_x1 >= in_total)
1822 entry->in_x1 = in_total - 1;
1823 entry->in_fraction1 = 0;
1825 // printf("OverlayFrame::translation_array_f 2 %d %d %d %f %f %f\n",
1829 // entry->in_fraction1,
1830 // entry->in_fraction2,
1831 // entry->output_fraction);
1868 #define TRANSLATE(max, temp_type, type, components, chroma_offset) \
1871 type **in_rows = (type**)input->get_rows(); \
1872 type **out_rows = (type**)output->get_rows(); \
1874 /* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \
1875 /* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \
1877 temp_type master_opacity = (temp_type)(alpha * max + 0.5); \
1878 temp_type master_transparency = max - master_opacity; \
1880 /* printf("TRANSLATE %d\n", mode); */ \
1882 for(int i = row1; i < row2; i++) \
1886 float y_fraction1_f; \
1887 float y_fraction2_f; \
1888 float y_output_fraction_f; \
1889 uint64_t y_fraction1_i; \
1890 uint64_t y_fraction2_i; \
1891 uint64_t y_output_fraction_i; \
1894 in_y1 = y_table_f[i - out_y1_int].in_x1; \
1895 in_y2 = y_table_f[i - out_y1_int].in_x2; \
1896 y_fraction1_f = y_table_f[i - out_y1_int].in_fraction1; \
1897 y_fraction2_f = y_table_f[i - out_y1_int].in_fraction2; \
1898 y_output_fraction_f = y_table_f[i - out_y1_int].output_fraction; \
1902 in_y1 = y_table_i[i - out_y1_int].in_x1; \
1903 in_y2 = y_table_i[i - out_y1_int].in_x2; \
1904 y_fraction1_i = y_table_i[i - out_y1_int].in_fraction1; \
1905 y_fraction2_i = y_table_i[i - out_y1_int].in_fraction2; \
1906 y_output_fraction_i = y_table_i[i - out_y1_int].output_fraction; \
1908 type *in_row1 = in_rows[(in_y1)]; \
1909 type *in_row2 = in_rows[(in_y2)]; \
1910 type *out_row = out_rows[i]; \
1912 for(int j = out_x1_int; j < out_x2_int; j++) \
1916 float x_fraction1_f; \
1917 float x_fraction2_f; \
1918 float x_output_fraction_f; \
1919 uint64_t x_fraction1_i; \
1920 uint64_t x_fraction2_i; \
1921 uint64_t x_output_fraction_i; \
1924 in_x1 = x_table_f[j - out_x1_int].in_x1; \
1925 in_x2 = x_table_f[j - out_x1_int].in_x2; \
1926 x_fraction1_f = x_table_f[j - out_x1_int].in_fraction1; \
1927 x_fraction2_f = x_table_f[j - out_x1_int].in_fraction2; \
1928 x_output_fraction_f = x_table_f[j - out_x1_int].output_fraction; \
1932 in_x1 = x_table_i[j - out_x1_int].in_x1; \
1933 in_x2 = x_table_i[j - out_x1_int].in_x2; \
1934 x_fraction1_i = x_table_i[j - out_x1_int].in_fraction1; \
1935 x_fraction2_i = x_table_i[j - out_x1_int].in_fraction2; \
1936 x_output_fraction_i = x_table_i[j - out_x1_int].output_fraction; \
1938 type *output = &out_row[j * components]; \
1939 type input1, input2, input3, input4; \
1943 float fraction1 = x_fraction1_f * y_fraction1_f; \
1944 float fraction2 = x_fraction2_f * y_fraction1_f; \
1945 float fraction3 = x_fraction1_f * y_fraction2_f; \
1946 float fraction4 = x_fraction2_f * y_fraction2_f; \
1948 input1 = (type)(in_row1[in_x1 * components] * fraction1 + \
1949 in_row1[in_x2 * components] * fraction2 + \
1950 in_row2[in_x1 * components] * fraction3 + \
1951 in_row2[in_x2 * components] * fraction4 + 0.5); \
1953 /* Add chroma to fractional pixels */ \
1956 float extra_chroma = (1.0F - \
1960 fraction4) * chroma_offset; \
1961 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
1962 in_row1[in_x2 * components + 1] * fraction2 + \
1963 in_row2[in_x1 * components + 1] * fraction3 + \
1964 in_row2[in_x2 * components + 1] * fraction4 + \
1965 extra_chroma + 0.5); \
1966 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
1967 in_row1[in_x2 * components + 2] * fraction2 + \
1968 in_row2[in_x1 * components + 2] * fraction3 + \
1969 in_row2[in_x2 * components + 2] * fraction4 + \
1970 extra_chroma + 0.5); \
1974 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
1975 in_row1[in_x2 * components + 1] * fraction2 + \
1976 in_row2[in_x1 * components + 1] * fraction3 + \
1977 in_row2[in_x2 * components + 1] * fraction4 + 0.5); \
1978 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
1979 in_row1[in_x2 * components + 2] * fraction2 + \
1980 in_row2[in_x1 * components + 2] * fraction3 + \
1981 in_row2[in_x2 * components + 2] * fraction4 + 0.5); \
1984 if(components == 4) \
1985 input4 = (type)(in_row1[in_x1 * components + 3] * fraction1 + \
1986 in_row1[in_x2 * components + 3] * fraction2 + \
1987 in_row2[in_x1 * components + 3] * fraction3 + \
1988 in_row2[in_x2 * components + 3] * fraction4 + 0.5); \
1992 uint64_t fraction1 = x_fraction1_i * y_fraction1_i; \
1993 uint64_t fraction2 = x_fraction2_i * y_fraction1_i; \
1994 uint64_t fraction3 = x_fraction1_i * y_fraction2_i; \
1995 uint64_t fraction4 = x_fraction2_i * y_fraction2_i; \
1997 input1 = (type)((in_row1[in_x1 * components] * fraction1 + \
1998 in_row1[in_x2 * components] * fraction2 + \
1999 in_row2[in_x1 * components] * fraction3 + \
2000 in_row2[in_x2 * components] * fraction4) / 0xffffffff); \
2002 /* Add chroma to fractional pixels */ \
2005 uint64_t extra_chroma = (0xffffffff - \
2011 input2 = (type)((in_row1[in_x1 * components + 1] * fraction1 + \
2012 in_row1[in_x2 * components + 1] * fraction2 + \
2013 in_row2[in_x1 * components + 1] * fraction3 + \
2014 in_row2[in_x2 * components + 1] * fraction4 + \
2015 extra_chroma) / 0xffffffff); \
2016 input3 = (type)((in_row1[in_x1 * components + 2] * fraction1 + \
2017 in_row1[in_x2 * components + 2] * fraction2 + \
2018 in_row2[in_x1 * components + 2] * fraction3 + \
2019 in_row2[in_x2 * components + 2] * fraction4 + \
2020 extra_chroma) / 0xffffffff); \
2024 input2 = (type)((in_row1[in_x1 * components + 1] * fraction1 + \
2025 in_row1[in_x2 * components + 1] * fraction2 + \
2026 in_row2[in_x1 * components + 1] * fraction3 + \
2027 in_row2[in_x2 * components + 1] * fraction4) / 0xffffffff); \
2028 input3 = (type)((in_row1[in_x1 * components + 2] * fraction1 + \
2029 in_row1[in_x2 * components + 2] * fraction2 + \
2030 in_row2[in_x1 * components + 2] * fraction3 + \
2031 in_row2[in_x2 * components + 2] * fraction4) / 0xffffffff); \
2034 if(components == 4) \
2035 input4 = (type)((in_row1[in_x1 * components + 3] * fraction1 + \
2036 in_row1[in_x2 * components + 3] * fraction2 + \
2037 in_row2[in_x1 * components + 3] * fraction3 + \
2038 in_row2[in_x2 * components + 3] * fraction4) / 0xffffffff); \
2041 temp_type opacity; \
2043 opacity = (temp_type)(master_opacity * \
2044 y_output_fraction_f * \
2045 x_output_fraction_f + 0.5); \
2047 opacity = (temp_type)((int64_t)master_opacity * \
2048 y_output_fraction_i * \
2049 x_output_fraction_i / \
2051 temp_type transparency = max - opacity; \
2053 /* printf("TRANSLATE 2 %x %d %d\n", opacity, j, i); */ \
2055 if(components == 3) \
2057 BLEND_3(max, temp_type, type, chroma_offset); \
2061 BLEND_4(max, temp_type, type, chroma_offset); \
2067 void TranslateUnit::process_package(LoadPackage *package)
2069 TranslatePackage *pkg = (TranslatePackage*)package;
2076 // Variables for TRANSLATE
2077 VFrame *input = engine->translate_input;
2078 VFrame *output = engine->translate_output;
2079 float in_x1 = engine->translate_in_x1;
2080 float in_y1 = engine->translate_in_y1;
2081 float in_x2 = engine->translate_in_x2;
2082 float in_y2 = engine->translate_in_y2;
2083 float out_x1 = engine->translate_out_x1;
2084 float out_y1 = engine->translate_out_y1;
2085 float out_x2 = engine->translate_out_x2;
2086 float out_y2 = engine->translate_out_y2;
2087 float alpha = engine->translate_alpha;
2088 int row1 = pkg->out_row1;
2089 int row2 = pkg->out_row2;
2090 int mode = engine->translate_mode;
2091 int in_total_x = input->get_w();
2092 int in_total_y = input->get_h();
2094 (engine->translate_input->get_color_model() == BC_YUV888 ||
2095 engine->translate_input->get_color_model() == BC_YUVA8888 ||
2096 engine->translate_input->get_color_model() == BC_YUV161616 ||
2097 engine->translate_input->get_color_model() == BC_YUVA16161616);
2099 transfer_table_f *x_table_f;
2100 transfer_table_f *y_table_f;
2101 transfer_table_i *x_table_i;
2102 transfer_table_i *y_table_i;
2106 translation_array_f(x_table_f,
2115 translation_array_f(y_table_f,
2127 translation_array_i(x_table_i,
2136 translation_array_i(y_table_i,
2146 // printf("TranslateUnit::process_package 1 %d\n", mode);
2150 switch(engine->translate_input->get_color_model())
2153 TRANSLATE(0xff, uint32_t, unsigned char, 3, 0);
2157 TRANSLATE(0xff, uint32_t, unsigned char, 4, 0);
2161 TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
2164 case BC_RGBA16161616:
2165 TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
2169 TRANSLATE(0xff, int32_t, unsigned char, 3, 0x80);
2173 TRANSLATE(0xff, int32_t, unsigned char, 4, 0x80);
2177 TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
2180 case BC_YUVA16161616:
2181 TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
2184 // printf("blend mode %i, took %li ms\n", mode, a.get_difference());
2188 delete [] x_table_f;
2189 delete [] y_table_f;
2193 delete [] x_table_i;
2194 delete [] y_table_i;
2207 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
2208 : LoadServer(cpus, cpus)
2210 this->overlay = overlay;
2213 TranslateEngine::~TranslateEngine()
2217 void TranslateEngine::init_packages()
2219 int out_y1_int = (int)translate_out_y1;
2220 int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h());
2221 int out_h = out_y2_int - out_y1_int;
2223 for(int i = 0; i < total_packages; i++)
2225 TranslatePackage *package = (TranslatePackage*)packages[i];
2226 package->out_row1 = (int)(out_y1_int + out_h /
2229 package->out_row2 = (int)((float)package->out_row1 +
2232 if(i >= total_packages - 1)
2233 package->out_row2 = out_y2_int;
2237 LoadClient* TranslateEngine::new_client()
2239 return new TranslateUnit(this, overlay);
2242 LoadPackage* TranslateEngine::new_package()
2244 return new TranslatePackage;
2254 #define SCALE_TRANSLATE(max, temp_type, type, components, chroma_offset) \
2256 temp_type opacity = (temp_type)(alpha * max + 0.5); \
2257 temp_type transparency = max - opacity; \
2258 int out_w = out_x2 - out_x1; \
2260 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
2262 int in_y = y_table[i - out_y1]; \
2263 type *in_row = (type*)in_rows[in_y] + in_x1 * components; \
2264 type *output = (type*)out_rows[i] + out_x1 * components; \
2266 /* X direction is scaled and requires a table lookup */ \
2267 if(out_w != in_x2 - in_x1) \
2269 for(int j = 0; j < out_w; j++) \
2271 type *in_row_plus_x = in_row + x_table[j] * components; \
2272 temp_type input1, input2, input3, input4; \
2274 input1 = in_row_plus_x[0]; \
2275 input2 = in_row_plus_x[1]; \
2276 input3 = in_row_plus_x[2]; \
2277 if(components == 4) \
2278 input4 = in_row_plus_x[3]; \
2280 if(components == 3) \
2282 BLEND_3(max, temp_type, type, chroma_offset); \
2286 BLEND_4(max, temp_type, type, chroma_offset); \
2288 output += components; \
2292 /* X direction is not scaled */ \
2294 for(int j = 0; j < out_w; j++) \
2296 temp_type input1, input2, input3, input4; \
2298 input1 = in_row[0]; \
2299 input2 = in_row[1]; \
2300 input3 = in_row[2]; \
2301 if(components == 4) \
2302 input4 = in_row[3]; \
2304 if(components == 3) \
2306 BLEND_3(max, temp_type, type, chroma_offset); \
2310 BLEND_4(max, temp_type, type, chroma_offset); \
2312 in_row += components; \
2313 output += components; \
2321 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
2322 : LoadClient(server)
2324 this->overlay = overlay;
2325 this->scale_translate = server;
2328 ScaleTranslateUnit::~ScaleTranslateUnit()
2332 void ScaleTranslateUnit::scale_array(int* &table,
2339 float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
2341 table = new int[out_x2 - out_x1];
2345 for(int i = 0; i < out_x2 - out_x1; i++)
2347 table[i] = (int)((float)i / scale + in_x1);
2352 for(int i = 0; i < out_x2 - out_x1; i++)
2354 table[i] = (int)((float)i / scale);
2360 void ScaleTranslateUnit::process_package(LoadPackage *package)
2362 ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
2364 // Args for NEAREST_NEIGHBOR_MACRO
2365 VFrame *output = scale_translate->output;
2366 VFrame *input = scale_translate->input;
2367 int in_x1 = scale_translate->in_x1;
2368 int in_y1 = scale_translate->in_y1;
2369 int in_x2 = scale_translate->in_x2;
2370 int in_y2 = scale_translate->in_y2;
2371 int out_x1 = scale_translate->out_x1;
2372 int out_y1 = scale_translate->out_y1;
2373 int out_x2 = scale_translate->out_x2;
2374 int out_y2 = scale_translate->out_y2;
2375 float alpha = scale_translate->alpha;
2376 int mode = scale_translate->mode;
2380 unsigned char **in_rows = input->get_rows();
2381 unsigned char **out_rows = output->get_rows();
2385 //printf("ScaleTranslateUnit::process_package 1 %d\n", mode);
2386 if(out_x2 - out_x1 != in_x2 - in_x1)
2388 scale_array(x_table,
2395 scale_array(y_table,
2403 switch(input->get_color_model())
2406 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 3, 0);
2410 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 3, 0x80);
2414 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 4, 0);
2418 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 4, 0x80);
2423 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
2427 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
2430 case BC_RGBA16161616:
2431 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
2434 case BC_YUVA16161616:
2435 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
2439 //printf("blend mode %i, took %li ms\n", mode, a.get_difference());
2440 if(out_x2 - out_x1 != in_x2 - in_x1)
2454 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
2455 : LoadServer(cpus, cpus)
2457 this->overlay = overlay;
2460 ScaleTranslateEngine::~ScaleTranslateEngine()
2464 void ScaleTranslateEngine::init_packages()
2466 int out_h = out_y2 - out_y1;
2468 for(int i = 0; i < total_packages; i++)
2470 ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i];
2471 package->out_row1 = (int)(out_y1 + out_h /
2474 package->out_row2 = (int)((float)package->out_row1 +
2477 if(i >= total_packages - 1)
2478 package->out_row2 = out_y2;
2482 LoadClient* ScaleTranslateEngine::new_client()
2484 return new ScaleTranslateUnit(this, overlay);
2487 LoadPackage* ScaleTranslateEngine::new_package()
2489 return new ScaleTranslatePackage;
2493 ScaleTranslatePackage::ScaleTranslatePackage()
2524 #define BLEND_ONLY(temp_type, type, max, components, chroma_offset) \
2526 temp_type opacity = (temp_type)(alpha * max + 0.5); \
2527 temp_type transparency = max - opacity; \
2529 type** output_rows = (type**)output->get_rows(); \
2530 type** input_rows = (type**)input->get_rows(); \
2531 int w = input->get_w(); \
2532 int h = input->get_h(); \
2534 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
2536 type* in_row = input_rows[i]; \
2537 type* output = output_rows[i]; \
2539 for(int j = 0; j < w; j++) \
2541 temp_type input1, input2, input3, input4; \
2542 input1 = in_row[0]; \
2543 input2 = in_row[1]; \
2544 input3 = in_row[2]; \
2545 if(components == 4) input4 = in_row[3]; \
2548 if(components == 3) \
2550 BLEND_3(max, temp_type, type, chroma_offset); \
2554 BLEND_4(max, temp_type, type, chroma_offset); \
2557 in_row += components; \
2558 output += components; \
2564 #define BLEND_ONLY_TRANSFER_REPLACE(type, components) \
2567 type** output_rows = (type**)output->get_rows(); \
2568 type** input_rows = (type**)input->get_rows(); \
2569 int w = input->get_w(); \
2570 int h = input->get_h(); \
2571 int line_len = w * sizeof(type) * components; \
2573 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
2575 memcpy(output_rows[i], input_rows[i], line_len); \
2579 // components is always 4
2580 #define BLEND_ONLY_4_NORMAL(temp_type, type, chroma_offset, maxbits) \
2582 temp_type opacity = (temp_type)(alpha * (((temp_type) 1) << maxbits) + 0.5); \
2583 temp_type maxsq = ((temp_type) 1) << (maxbits * 2) ; \
2585 type** output_rows = (type**)output->get_rows(); \
2586 type** input_rows = (type**)input->get_rows(); \
2587 int w = input->get_w(); \
2588 int h = input->get_h(); \
2590 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
2592 type* in_row = input_rows[i]; \
2593 type* output = output_rows[i]; \
2595 for(int j = 0; j < w; j++) \
2597 temp_type pixel_opacity, pixel_transparency; \
2598 pixel_opacity = opacity * in_row[3]; \
2599 pixel_transparency = (temp_type)maxsq - pixel_opacity; \
2602 output[0] = (type)(((temp_type)in_row[0] * pixel_opacity + \
2603 (temp_type)output[0] * pixel_transparency) >> (maxbits * 2)); \
2604 output[1] = (type)(((((temp_type)in_row[1] - chroma_offset) * pixel_opacity + \
2605 ((temp_type)output[1] - chroma_offset) * pixel_transparency) \
2606 >> (maxbits * 2)) + \
2608 output[2] = (type)(((((temp_type)in_row[2] - chroma_offset) * pixel_opacity + \
2609 ((temp_type)output[2] - chroma_offset) * pixel_transparency) \
2610 >> (maxbits * 2)) + \
2612 output[3] = (type)(in_row[3] > output[3] ? in_row[3] : output[3]); \
2620 // components is always 3
2621 #define BLEND_ONLY_3_NORMAL(temp_type, type, chroma_offset, maxbits) \
2623 temp_type opacity = (temp_type)(alpha * (((temp_type) 1) << maxbits) + 0.5); \
2624 temp_type transparency = (((temp_type) 1) << maxbits) - opacity; \
2626 type** output_rows = (type**)output->get_rows(); \
2627 type** input_rows = (type**)input->get_rows(); \
2628 int w = input->get_w() * 3; \
2629 int h = input->get_h(); \
2631 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
2633 type* in_row = input_rows[i]; \
2634 type* output = output_rows[i]; \
2636 for(int j = 0; j < w; j++) /* w = 3x width! */ \
2638 *output = (type)((temp_type)*in_row * opacity + *output * transparency) >> maxbits; \
2646 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
2647 : LoadClient(server)
2649 this->overlay = overlay;
2650 this->blend_engine = server;
2653 BlendUnit::~BlendUnit()
2657 void BlendUnit::process_package(LoadPackage *package)
2659 BlendPackage *pkg = (BlendPackage*)package;
2662 VFrame *output = blend_engine->output;
2663 VFrame *input = blend_engine->input;
2664 float alpha = blend_engine->alpha;
2665 if (alpha > 1.0) alpha = 1.0;
2666 int mode = blend_engine->mode;
2668 if (mode == TRANSFER_REPLACE)
2670 switch(input->get_color_model())
2674 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 3);
2678 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 4);
2682 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 3);
2684 case BC_RGBA16161616:
2685 case BC_YUVA16161616:
2686 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 4);
2691 if (mode == TRANSFER_NORMAL)
2693 switch(input->get_color_model())
2696 BLEND_ONLY_3_NORMAL(uint32_t, unsigned char, 0, 8);
2699 BLEND_ONLY_3_NORMAL(int32_t, unsigned char, 0x80, 8);
2702 BLEND_ONLY_4_NORMAL(uint32_t, unsigned char, 0, 8);
2705 BLEND_ONLY_4_NORMAL(int32_t, unsigned char, 0x80, 8);
2708 BLEND_ONLY_3_NORMAL(uint64_t, uint16_t, 0, 16);
2711 BLEND_ONLY_3_NORMAL(int64_t, uint16_t, 0x8000, 16);
2713 case BC_RGBA16161616:
2714 BLEND_ONLY_4_NORMAL(uint64_t, uint16_t, 0, 16);
2716 case BC_YUVA16161616:
2717 BLEND_ONLY_4_NORMAL(int64_t, uint16_t, 0x8000, 16);
2722 switch(input->get_color_model())
2725 BLEND_ONLY(uint32_t, unsigned char, 0xff, 3, 0);
2728 BLEND_ONLY(int32_t, unsigned char, 0xff, 3, 0x80);
2731 BLEND_ONLY(uint32_t, unsigned char, 0xff, 4, 0);
2734 BLEND_ONLY(int32_t, unsigned char, 0xff, 4, 0x80);
2737 BLEND_ONLY(uint64_t, uint16_t, 0xffff, 3, 0);
2740 BLEND_ONLY(int64_t, uint16_t, 0xffff, 3, 0x8000);
2742 case BC_RGBA16161616:
2743 BLEND_ONLY(uint64_t, uint16_t, 0xffff, 4, 0);
2745 case BC_YUVA16161616:
2746 BLEND_ONLY(int64_t, uint16_t, 0xffff, 4, 0x8000);
2753 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
2754 : LoadServer(cpus, cpus)
2756 this->overlay = overlay;
2759 BlendEngine::~BlendEngine()
2763 void BlendEngine::init_packages()
2765 for(int i = 0; i < total_packages; i++)
2767 BlendPackage *package = (BlendPackage*)packages[i];
2768 package->out_row1 = (int)(input->get_h() /
2771 package->out_row2 = (int)((float)package->out_row1 +
2775 if(i >= total_packages - 1)
2776 package->out_row2 = input->get_h();
2780 LoadClient* BlendEngine::new_client()
2782 return new BlendUnit(this, overlay);
2785 LoadPackage* BlendEngine::new_package()
2787 return new BlendPackage;
2791 BlendPackage::BlendPackage()