00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdint.h>
00005 #include <stdlib.h>
00006 #include <unistd.h>
00007
00008 #include "clip.h"
00009 #include "edl.inc"
00010 #include "mutex.h"
00011 #include "overlayframe.h"
00012 #include "units.h"
00013 #include "vframe.h"
00014
00015
00016
00017 static int my_abs(int32_t x)
00018 {
00019 return abs(x);
00020 }
00021
00022 static int my_abs(uint32_t x)
00023 {
00024 return x;
00025 }
00026
00027 static int my_abs(int64_t x)
00028 {
00029 return llabs(x);
00030 }
00031
00032 static int my_abs(uint64_t x)
00033 {
00034 return x;
00035 }
00036
00037 static float my_abs(float x)
00038 {
00039 return fabsf(x);
00040 }
00041
00042
00043
00044
00045 OverlayFrame::OverlayFrame(int cpus)
00046 {
00047 temp_frame = 0;
00048 blend_engine = 0;
00049 scale_engine = 0;
00050 scaletranslate_engine = 0;
00051 translate_engine = 0;
00052 this->cpus = cpus;
00053 }
00054
00055 OverlayFrame::~OverlayFrame()
00056 {
00057 if(temp_frame) delete temp_frame;
00058 if(scale_engine) delete scale_engine;
00059 if(translate_engine) delete translate_engine;
00060 if(blend_engine) delete blend_engine;
00061 if(scaletranslate_engine) delete scaletranslate_engine;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define BLEND_3(max, temp_type, type, chroma_offset) \
00083 { \
00084 temp_type r, g, b; \
00085 \
00086 \
00087 switch(mode) \
00088 { \
00089 case TRANSFER_DIVIDE: \
00090 r = output[0] ? (((temp_type)input1 * max) / output[0]) : max; \
00091 if(chroma_offset) \
00092 { \
00093 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
00094 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
00095 } \
00096 else \
00097 { \
00098 g = output[1] ? (temp_type)input2 * max / (temp_type)output[1] : max; \
00099 b = output[2] ? (temp_type)input3 * max / (temp_type)output[2] : max; \
00100 } \
00101 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
00102 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
00103 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
00104 break; \
00105 case TRANSFER_MULTIPLY: \
00106 r = ((temp_type)input1 * output[0]) / max; \
00107 if(chroma_offset) \
00108 { \
00109 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
00110 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
00111 } \
00112 else \
00113 { \
00114 g = (temp_type)input2 * (temp_type)output[1] / max; \
00115 b = (temp_type)input3 * (temp_type)output[2] / max; \
00116 } \
00117 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
00118 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
00119 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
00120 break; \
00121 case TRANSFER_SUBTRACT: \
00122 r = (temp_type)output[0] - (temp_type)input1; \
00123 g = ((temp_type)output[1] - (temp_type)chroma_offset) - \
00124 ((temp_type)input2 - (temp_type)chroma_offset) + \
00125 (temp_type)chroma_offset; \
00126 b = ((temp_type)output[2] - (temp_type)chroma_offset) - \
00127 ((temp_type)input3 - (temp_type)chroma_offset) + \
00128 (temp_type)chroma_offset; \
00129 r = (r * opacity + output[0] * transparency) / max; \
00130 g = (g * opacity + output[1] * transparency) / max; \
00131 b = (b * opacity + output[2] * transparency) / max; \
00132 break; \
00133 case TRANSFER_ADDITION: \
00134 r = (temp_type)input1 + output[0]; \
00135 g = ((temp_type)input2 - chroma_offset) + \
00136 ((temp_type)output[1] - chroma_offset) + \
00137 (temp_type)chroma_offset; \
00138 b = ((temp_type)input3 - chroma_offset) + \
00139 ((temp_type)output[2] - chroma_offset) + \
00140 (temp_type)chroma_offset; \
00141 r = (r * opacity + output[0] * transparency) / max; \
00142 g = (g * opacity + output[1] * transparency) / max; \
00143 b = (b * opacity + output[2] * transparency) / max; \
00144 break; \
00145 case TRANSFER_REPLACE: \
00146 r = input1; \
00147 g = input2; \
00148 b = input3; \
00149 break; \
00150 case TRANSFER_NORMAL: \
00151 r = ((temp_type)input1 * opacity + output[0] * transparency) / max; \
00152 g = ((temp_type)input2 * opacity + output[1] * transparency) / max; \
00153 b = ((temp_type)input3 * opacity + output[2] * transparency) / max; \
00154 break; \
00155 } \
00156 \
00157 if(sizeof(type) != 4) \
00158 { \
00159 output[0] = (type)CLIP(r, 0, max); \
00160 output[1] = (type)CLIP(g, 0, max); \
00161 output[2] = (type)CLIP(b, 0, max); \
00162 } \
00163 else \
00164 { \
00165 output[0] = r; \
00166 output[1] = g; \
00167 output[2] = b; \
00168 } \
00169 }
00170
00171
00172
00173
00174
00175
00176 #define BLEND_4(max, temp_type, type, chroma_offset) \
00177 { \
00178 temp_type r, g, b, a; \
00179 temp_type pixel_opacity, pixel_transparency; \
00180 temp_type output1 = output[0]; \
00181 temp_type output2 = output[1]; \
00182 temp_type output3 = output[2]; \
00183 temp_type output4 = output[3]; \
00184 \
00185 pixel_opacity = opacity * input4; \
00186 pixel_transparency = (temp_type)max * max - pixel_opacity; \
00187 \
00188 switch(mode) \
00189 { \
00190 case TRANSFER_DIVIDE: \
00191 r = output1 ? (((temp_type)input1 * max) / output1) : max; \
00192 if(chroma_offset) \
00193 { \
00194 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output2 - chroma_offset) ? input2 : output2; \
00195 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output3 - chroma_offset) ? input3 : output3; \
00196 } \
00197 else \
00198 { \
00199 g = output2 ? (temp_type)input2 * max / (temp_type)output2 : max; \
00200 b = output3 ? (temp_type)input3 * max / (temp_type)output3 : max; \
00201 } \
00202 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
00203 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
00204 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
00205 a = input4 > output4 ? input4 : output4; \
00206 break; \
00207 case TRANSFER_MULTIPLY: \
00208 r = ((temp_type)input1 * output1) / max; \
00209 if(chroma_offset) \
00210 { \
00211 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output2 - chroma_offset) ? input2 : output2; \
00212 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output3 - chroma_offset) ? input3 : output3; \
00213 } \
00214 else \
00215 { \
00216 g = (temp_type)input2 * (temp_type)output2 / max; \
00217 b = (temp_type)input3 * (temp_type)output3 / max; \
00218 } \
00219 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
00220 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
00221 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
00222 a = input4 > output4 ? input4 : output4; \
00223 break; \
00224 case TRANSFER_SUBTRACT: \
00225 r = (temp_type)input1 - output1; \
00226 g = ((temp_type)output2 - chroma_offset) - \
00227 ((temp_type)input2 - (temp_type)chroma_offset) + \
00228 (temp_type)chroma_offset; \
00229 b = ((temp_type)output3 - chroma_offset) - \
00230 ((temp_type)input3 - (temp_type)chroma_offset) + \
00231 (temp_type)chroma_offset; \
00232 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
00233 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
00234 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
00235 a = input4 > output4 ? input4 : output4; \
00236 break; \
00237 case TRANSFER_ADDITION: \
00238 r = (temp_type)input1 + output1; \
00239 g = ((temp_type)input2 - chroma_offset) + \
00240 ((temp_type)output2 - chroma_offset) + \
00241 chroma_offset; \
00242 b = ((temp_type)input3 - chroma_offset) + \
00243 ((temp_type)output3 - chroma_offset) + \
00244 chroma_offset; \
00245 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
00246 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
00247 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
00248 a = input4 > output4 ? input4 : output4; \
00249 break; \
00250 case TRANSFER_REPLACE: \
00251 r = input1; \
00252 g = input2; \
00253 b = input3; \
00254 a = input4; \
00255 break; \
00256 case TRANSFER_NORMAL: \
00257 r = (input1 * pixel_opacity + \
00258 output1 * pixel_transparency) / max / max; \
00259 g = ((input2 - chroma_offset) * pixel_opacity + \
00260 (output2 - chroma_offset) * pixel_transparency) \
00261 / max / max + \
00262 chroma_offset; \
00263 b = ((input3 - chroma_offset) * pixel_opacity + \
00264 (output3 - chroma_offset) * pixel_transparency) \
00265 / max / max + \
00266 chroma_offset; \
00267 a = input4 > output4 ? input4 : output4; \
00268 break; \
00269 } \
00270 \
00271 if(sizeof(type) != 4) \
00272 { \
00273 output[0] = (type)CLIP(r, 0, max); \
00274 output[1] = (type)CLIP(g, 0, max); \
00275 output[2] = (type)CLIP(b, 0, max); \
00276 output[3] = (type)a; \
00277 } \
00278 else \
00279 { \
00280 output[0] = r; \
00281 output[1] = g; \
00282 output[2] = b; \
00283 output[3] = a; \
00284 } \
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 int OverlayFrame::overlay(VFrame *output,
00297 VFrame *input,
00298 float in_x1,
00299 float in_y1,
00300 float in_x2,
00301 float in_y2,
00302 float out_x1,
00303 float out_y1,
00304 float out_x2,
00305 float out_y2,
00306 float alpha,
00307 int mode,
00308 int interpolation_type)
00309 {
00310 float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
00311 float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
00312
00313
00314
00315
00316
00317
00318
00319
00320 if(isnan(in_x1) ||
00321 isnan(in_y1) ||
00322 isnan(in_x2) ||
00323 isnan(in_y2) ||
00324 isnan(out_x1) ||
00325 isnan(out_y1) ||
00326 isnan(out_x2) ||
00327 isnan(out_y2)) return 1;
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 if(in_x1 < 0)
00341 {
00342 out_x1 += -in_x1 * w_scale;
00343 in_x1 = 0;
00344 }
00345 else
00346 if(in_x1 >= input->get_w())
00347 {
00348 out_x1 -= (in_x1 - input->get_w()) * w_scale;
00349 in_x1 = input->get_w();
00350 }
00351
00352 if(in_y1 < 0)
00353 {
00354 out_y1 += -in_y1 * h_scale;
00355 in_y1 = 0;
00356 }
00357 else
00358 if(in_y1 >= input->get_h())
00359 {
00360 out_y1 -= (in_y1 - input->get_h()) * h_scale;
00361 in_y1 = input->get_h();
00362 }
00363
00364 if(in_x2 < 0)
00365 {
00366 out_x2 += -in_x2 * w_scale;
00367 in_x2 = 0;
00368 }
00369 else
00370 if(in_x2 >= input->get_w())
00371 {
00372 out_x2 -= (in_x2 - input->get_w()) * w_scale;
00373 in_x2 = input->get_w();
00374 }
00375
00376 if(in_y2 < 0)
00377 {
00378 out_y2 += -in_y2 * h_scale;
00379 in_y2 = 0;
00380 }
00381 else
00382 if(in_y2 >= input->get_h())
00383 {
00384 out_y2 -= (in_y2 - input->get_h()) * h_scale;
00385 in_y2 = input->get_h();
00386 }
00387
00388 if(out_x1 < 0)
00389 {
00390 in_x1 += -out_x1 / w_scale;
00391 out_x1 = 0;
00392 }
00393 else
00394 if(out_x1 >= output->get_w())
00395 {
00396 in_x1 -= (out_x1 - output->get_w()) / w_scale;
00397 out_x1 = output->get_w();
00398 }
00399
00400 if(out_y1 < 0)
00401 {
00402 in_y1 += -out_y1 / h_scale;
00403 out_y1 = 0;
00404 }
00405 else
00406 if(out_y1 >= output->get_h())
00407 {
00408 in_y1 -= (out_y1 - output->get_h()) / h_scale;
00409 out_y1 = output->get_h();
00410 }
00411
00412 if(out_x2 < 0)
00413 {
00414 in_x2 += -out_x2 / w_scale;
00415 out_x2 = 0;
00416 }
00417 else
00418 if(out_x2 >= output->get_w())
00419 {
00420 in_x2 -= (out_x2 - output->get_w()) / w_scale;
00421 out_x2 = output->get_w();
00422 }
00423
00424 if(out_y2 < 0)
00425 {
00426 in_y2 += -out_y2 / h_scale;
00427 out_y2 = 0;
00428 }
00429 else
00430 if(out_y2 >= output->get_h())
00431 {
00432 in_y2 -= (out_y2 - output->get_h()) / h_scale;
00433 out_y2 = output->get_h();
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 float in_w = in_x2 - in_x1;
00446 float in_h = in_y2 - in_y1;
00447 float out_w = out_x2 - out_x1;
00448 float out_h = out_y2 - out_y1;
00449
00450 VFrame *translation_input = input;
00451
00452
00453 if(in_w <= 0 || in_h <= 0 || out_w <= 0 || out_h <= 0) return 0;
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 if(interpolation_type != NEAREST_NEIGHBOR &&
00473 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
00474 {
00475
00476 int in_x1_int = (int)in_x1;
00477 int in_y1_int = (int)in_y1;
00478 int in_x2_int = MIN((int)ceil(in_x2), input->get_w());
00479 int in_y2_int = MIN((int)ceil(in_y2), input->get_h());
00480 int out_x1_int = (int)out_x1;
00481 int out_y1_int = (int)out_y1;
00482 int out_x2_int = MIN((int)ceil(out_x2), output->get_w());
00483 int out_y2_int = MIN((int)ceil(out_y2), output->get_h());
00484
00485
00486 int temp_w = (out_x2_int - out_x1_int);
00487 int temp_h = (out_y2_int - out_y1_int);
00488 VFrame *scale_output;
00489
00490
00491
00492 #define NO_TRANSLATION1 \
00493 (EQUIV(in_x1, 0) && \
00494 EQUIV(in_y1, 0) && \
00495 EQUIV(out_x1, 0) && \
00496 EQUIV(out_y1, 0) && \
00497 EQUIV(in_x2, in_x2_int) && \
00498 EQUIV(in_y2, in_y2_int) && \
00499 EQUIV(out_x2, temp_w) && \
00500 EQUIV(out_y2, temp_h))
00501
00502
00503 #define NO_BLEND \
00504 (EQUIV(alpha, 1) && \
00505 (mode == TRANSFER_REPLACE || \
00506 (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 if(NO_TRANSLATION1 &&
00518 NO_BLEND)
00519 {
00520
00521
00522 scale_output = output;
00523 translation_input = 0;
00524 }
00525 else
00526
00527
00528 {
00529 if(temp_frame &&
00530 (temp_frame->get_w() != temp_w ||
00531 temp_frame->get_h() != temp_h))
00532 {
00533 delete temp_frame;
00534 temp_frame = 0;
00535 }
00536
00537 if(!temp_frame)
00538 {
00539 temp_frame = new VFrame(0,
00540 temp_w,
00541 temp_h,
00542 input->get_color_model(),
00543 -1);
00544 }
00545
00546
00547
00548 temp_frame->clear_frame();
00549
00550
00551
00552 scale_output = temp_frame;
00553 translation_input = scale_output;
00554
00555
00556 in_x1 = 0;
00557 in_y1 = 0;
00558 in_x2 = temp_w;
00559 in_y2 = temp_h;
00560 }
00561
00562
00563
00564
00565
00566
00567 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
00568 scale_engine->scale_output = scale_output;
00569 scale_engine->scale_input = input;
00570 scale_engine->w_scale = w_scale;
00571 scale_engine->h_scale = h_scale;
00572 scale_engine->in_x1_int = in_x1_int;
00573 scale_engine->in_y1_int = in_y1_int;
00574 scale_engine->out_w_int = temp_w;
00575 scale_engine->out_h_int = temp_h;
00576 scale_engine->interpolation_type = interpolation_type;
00577
00578
00579
00580 scale_engine->process_packages();
00581
00582
00583
00584
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 #define NO_TRANSLATION2 \
00602 (EQUIV(in_x1, 0) && \
00603 EQUIV(in_y1, 0) && \
00604 EQUIV(in_x2, translation_input->get_w()) && \
00605 EQUIV(in_y2, translation_input->get_h()) && \
00606 EQUIV(out_x1, 0) && \
00607 EQUIV(out_y1, 0) && \
00608 EQUIV(out_x2, output->get_w()) && \
00609 EQUIV(out_y2, output->get_h())) \
00610
00611 #define NO_SCALE \
00612 (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
00613 EQUIV(out_y2 - out_y1, in_y2 - in_y1))
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 if(translation_input)
00624 {
00625
00626 if( NO_TRANSLATION2 &&
00627 NO_SCALE &&
00628 NO_BLEND)
00629 {
00630
00631 output->copy_from(translation_input);
00632 }
00633 else
00634
00635 if( NO_TRANSLATION2 &&
00636 NO_SCALE)
00637 {
00638 if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
00639
00640
00641 blend_engine->output = output;
00642 blend_engine->input = translation_input;
00643 blend_engine->alpha = alpha;
00644 blend_engine->mode = mode;
00645
00646 blend_engine->process_packages();
00647 }
00648 else
00649
00650
00651 if(interpolation_type == NEAREST_NEIGHBOR ||
00652 EQUIV(in_x1, (int)in_x1) &&
00653 EQUIV(in_y1, (int)in_y1) &&
00654 EQUIV(in_x2, (int)in_x2) &&
00655 EQUIV(in_y2, (int)in_y2) &&
00656
00657 EQUIV(out_x1, (int)out_x1) &&
00658 EQUIV(out_y1, (int)out_y1) &&
00659 EQUIV(out_x2, (int)out_x2) &&
00660 EQUIV(out_y2, (int)out_y2))
00661 {
00662
00663 if(!scaletranslate_engine) scaletranslate_engine =
00664 new ScaleTranslateEngine(this, cpus);
00665
00666
00667 scaletranslate_engine->output = output;
00668 scaletranslate_engine->input = translation_input;
00669 scaletranslate_engine->in_x1 = (int)in_x1;
00670 scaletranslate_engine->in_y1 = (int)in_y1;
00671
00672
00673 scaletranslate_engine->in_x2 = (int)in_x1 + (int)(in_x2 - in_x1);
00674 scaletranslate_engine->in_y2 = (int)in_y1 + (int)(in_y2 - in_y1);
00675 scaletranslate_engine->out_x1 = (int)out_x1;
00676 scaletranslate_engine->out_y1 = (int)out_y1;
00677 scaletranslate_engine->out_x2 = (int)out_x1 + (int)(out_x2 - out_x1);
00678 scaletranslate_engine->out_y2 = (int)out_y1 + (int)(out_y2 - out_y1);
00679 scaletranslate_engine->alpha = alpha;
00680 scaletranslate_engine->mode = mode;
00681
00682 scaletranslate_engine->process_packages();
00683 }
00684 else
00685
00686 {
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
00700 translate_engine->translate_output = output;
00701 translate_engine->translate_input = translation_input;
00702 translate_engine->translate_in_x1 = in_x1;
00703 translate_engine->translate_in_y1 = in_y1;
00704 translate_engine->translate_in_x2 = in_x2;
00705 translate_engine->translate_in_y2 = in_y2;
00706 translate_engine->translate_out_x1 = out_x1;
00707 translate_engine->translate_out_y1 = out_y1;
00708 translate_engine->translate_out_x2 = out_x2;
00709 translate_engine->translate_out_y2 = out_y2;
00710 translate_engine->translate_alpha = alpha;
00711 translate_engine->translate_mode = mode;
00712
00713
00714
00715 translate_engine->process_packages();
00716
00717 }
00718 }
00719
00720
00721 return 0;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730 ScalePackage::ScalePackage()
00731 {
00732 }
00733
00734
00735
00736
00737 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
00738 : LoadClient(server)
00739 {
00740 this->overlay = overlay;
00741 this->engine = server;
00742 }
00743
00744 ScaleUnit::~ScaleUnit()
00745 {
00746 }
00747
00748
00749
00750 void ScaleUnit::tabulate_reduction(bilinear_table_t* &table,
00751 float scale,
00752 int in_pixel1,
00753 int out_total,
00754 int in_total)
00755 {
00756 table = new bilinear_table_t[out_total];
00757 bzero(table, sizeof(bilinear_table_t) * out_total);
00758
00759 for(int i = 0; i < out_total; i++)
00760 {
00761 float out_start = i;
00762 float in_start = out_start * scale;
00763 float out_end = i + 1;
00764 float in_end = out_end * scale;
00765 bilinear_table_t *entry = table + i;
00766
00767
00768
00769 entry->input_fraction1 = (floor(in_start + 1) - in_start) ;
00770 entry->input_fraction2 = 1.0 ;
00771 entry->input_fraction3 = (in_end - floor(in_end)) ;
00772
00773 if(in_end >= in_total - in_pixel1)
00774 {
00775 in_end = in_total - in_pixel1 - 1;
00776
00777 int difference = (int)in_end - (int)in_start - 1;
00778 if(difference < 0) difference = 0;
00779 entry->input_fraction3 = 1.0 -
00780 entry->input_fraction1 -
00781 entry->input_fraction2 * difference;
00782 }
00783
00784
00785 entry->input_pixel1 = (int)in_start;
00786 entry->input_pixel2 = (int)in_end;
00787
00788
00789 if(entry->input_pixel2 > entry->input_pixel1 + 1)
00790 {
00791 float total = entry->input_fraction1 +
00792 entry->input_fraction2 *
00793 (entry->input_pixel2 - entry->input_pixel1 - 1) +
00794 entry->input_fraction3;
00795 entry->input_fraction1 /= total;
00796 entry->input_fraction2 /= total;
00797 entry->input_fraction3 /= total;
00798 }
00799 else
00800 {
00801 float total = entry->input_fraction1 +
00802 entry->input_fraction3;
00803 entry->input_fraction1 /= total;
00804 entry->input_fraction3 /= total;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 if(entry->input_pixel1 > entry->input_pixel2)
00822 {
00823 entry->input_pixel1 = entry->input_pixel2;
00824 entry->input_fraction1 = 0;
00825 }
00826
00827
00828
00829 entry->total_fraction =
00830 entry->input_fraction1 +
00831 entry->input_fraction2 * (entry->input_pixel2 - entry->input_pixel1 - 1) +
00832 entry->input_fraction3;
00833 entry->input_pixel1 += in_pixel1;
00834 entry->input_pixel2 += in_pixel1;
00835 }
00836 }
00837
00838 void ScaleUnit::tabulate_enlarge(bilinear_table_t* &table,
00839 float scale,
00840 int in_pixel1,
00841 int out_total,
00842 int in_total)
00843 {
00844 table = new bilinear_table_t[out_total];
00845 bzero(table, sizeof(bilinear_table_t) * out_total);
00846
00847 for(int i = 0; i < out_total; i++)
00848 {
00849 bilinear_table_t *entry = table + i;
00850 float in_pixel = i * scale;
00851 entry->input_pixel1 = (int)floor(in_pixel);
00852 entry->input_pixel2 = entry->input_pixel1 + 1;
00853
00854 if(in_pixel <= in_total)
00855 {
00856 entry->input_fraction3 = in_pixel - entry->input_pixel1;
00857 }
00858 else
00859 {
00860 entry->input_fraction3 = 0;
00861 entry->input_pixel2 = 0;
00862 }
00863
00864 if(in_pixel >= 0)
00865 {
00866 entry->input_fraction1 = entry->input_pixel2 - in_pixel;
00867 }
00868 else
00869 {
00870 entry->input_fraction1 = 0;
00871 entry->input_pixel1 = 0;
00872 }
00873
00874 if(entry->input_pixel2 >= in_total - in_pixel1)
00875 {
00876 entry->input_pixel2 = entry->input_pixel1;
00877 entry->input_fraction3 = 1.0 - entry->input_fraction1;
00878 }
00879
00880 entry->total_fraction =
00881 entry->input_fraction1 +
00882 entry->input_fraction3;
00883 entry->input_pixel1 += in_pixel1;
00884 entry->input_pixel2 += in_pixel1;
00885
00886
00887
00888
00889
00890
00891
00892 }
00893 }
00894
00895 void ScaleUnit::dump_bilinear(bilinear_table_t *table, int total)
00896 {
00897 printf("ScaleUnit::dump_bilinear\n");
00898 for(int i = 0; i < total; i++)
00899 {
00900 printf("out=%d inpixel1=%d inpixel2=%d infrac1=%f infrac2=%f infrac3=%f total=%f\n",
00901 i,
00902 table[i].input_pixel1,
00903 table[i].input_pixel2,
00904 table[i].input_fraction1,
00905 table[i].input_fraction2,
00906 table[i].input_fraction3,
00907 table[i].total_fraction);
00908 }
00909 }
00910
00911 #define PIXEL_REDUCE_MACRO(type, components, row) \
00912 { \
00913 type *input_row = &in_rows[row][x_entry->input_pixel1 * components]; \
00914 type *input_end = &in_rows[row][x_entry->input_pixel2 * components]; \
00915 \
00916 \
00917 temp_f1 += input_scale1 * input_row[0]; \
00918 temp_f2 += input_scale1 * input_row[1]; \
00919 temp_f3 += input_scale1 * input_row[2]; \
00920 if(components == 4) temp_f4 += input_scale1 * input_row[3]; \
00921 \
00922 \
00923 \
00924 { \
00925 temp_f1 += input_scale3 * input_end[0]; \
00926 temp_f2 += input_scale3 * input_end[1]; \
00927 temp_f3 += input_scale3 * input_end[2]; \
00928 if(components == 4) temp_f4 += input_scale3 * input_end[3]; \
00929 } \
00930 \
00931 \
00932 for(input_row += components; input_row < input_end; input_row += components) \
00933 { \
00934 temp_f1 += input_scale2 * input_row[0]; \
00935 temp_f2 += input_scale2 * input_row[1]; \
00936 temp_f3 += input_scale2 * input_row[2]; \
00937 if(components == 4) temp_f4 += input_scale2 * input_row[3]; \
00938 } \
00939 }
00940
00941
00942
00943 #define BILINEAR_REDUCE(max, type, components) \
00944 { \
00945 bilinear_table_t *x_table, *y_table; \
00946 int out_h = pkg->out_row2 - pkg->out_row1; \
00947 type **in_rows = (type**)input->get_rows(); \
00948 type **out_rows = (type**)output->get_rows(); \
00949 \
00950 if(scale_w < 1) \
00951 tabulate_reduction(x_table, \
00952 1.0 / scale_w, \
00953 in_x1_int, \
00954 out_w_int, \
00955 input->get_w()); \
00956 else \
00957 tabulate_enlarge(x_table, \
00958 1.0 / scale_w, \
00959 in_x1_int, \
00960 out_w_int, \
00961 input->get_w()); \
00962 \
00963 if(scale_h < 1) \
00964 tabulate_reduction(y_table, \
00965 1.0 / scale_h, \
00966 in_y1_int, \
00967 out_h_int, \
00968 input->get_h()); \
00969 else \
00970 tabulate_enlarge(y_table, \
00971 1.0 / scale_h, \
00972 in_y1_int, \
00973 out_h_int, \
00974 input->get_h()); \
00975 \
00976 \
00977 for(int i = 0; i < out_h; i++) \
00978 { \
00979 type *out_row = out_rows[i + pkg->out_row1]; \
00980 bilinear_table_t *y_entry = &y_table[i + pkg->out_row1]; \
00981 \
00982 \
00983 \
00984 \
00985 \
00986 \
00987 \
00988 \
00989 for(int j = 0; j < out_w_int; j++) \
00990 { \
00991 bilinear_table_t *x_entry = &x_table[j]; \
00992 \
00993 float temp_f1; \
00994 float temp_f2; \
00995 float temp_f3; \
00996 float temp_f4; \
00997 if(sizeof(type) != 4) \
00998 temp_f1 = temp_f2 = temp_f3 = temp_f4 = .5; \
00999 else \
01000 temp_f1 = temp_f2 = temp_f3 = temp_f4 = 0; \
01001 \
01002 \
01003 float input_scale1 = y_entry->input_fraction1 * x_entry->input_fraction1; \
01004 float input_scale2 = y_entry->input_fraction1 * x_entry->input_fraction2; \
01005 float input_scale3 = y_entry->input_fraction1 * x_entry->input_fraction3; \
01006 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel1) \
01007 \
01008 \
01009 if(out_h) \
01010 { \
01011 input_scale1 = y_entry->input_fraction3 * x_entry->input_fraction1; \
01012 input_scale2 = y_entry->input_fraction3 * x_entry->input_fraction2; \
01013 input_scale3 = y_entry->input_fraction3 * x_entry->input_fraction3; \
01014 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel2) \
01015 \
01016 \
01017 if(out_h > 1) \
01018 { \
01019 input_scale1 = y_entry->input_fraction2 * x_entry->input_fraction1; \
01020 input_scale2 = y_entry->input_fraction2 * x_entry->input_fraction2; \
01021 input_scale3 = y_entry->input_fraction2 * x_entry->input_fraction3; \
01022 for(int k = y_entry->input_pixel1 + 1; \
01023 k < y_entry->input_pixel2; \
01024 k++) \
01025 { \
01026 PIXEL_REDUCE_MACRO(type, components, k) \
01027 } \
01028 } \
01029 } \
01030 \
01031 \
01032 if(max != 1.0) \
01033 { \
01034 if(temp_f1 > max) temp_f1 = max; \
01035 if(temp_f2 > max) temp_f2 = max; \
01036 if(temp_f3 > max) temp_f3 = max; \
01037 if(components == 4) if(temp_f4 > max) temp_f4 = max; \
01038 } \
01039 \
01040 out_row[j * components ] = (type)temp_f1; \
01041 out_row[j * components + 1] = (type)temp_f2; \
01042 out_row[j * components + 2] = (type)temp_f3; \
01043 if(components == 4) out_row[j * components + 3] = (type)temp_f4; \
01044 } \
01045 \
01046 } \
01047 \
01048 delete [] x_table; \
01049 delete [] y_table; \
01050 }
01051
01052
01053
01054
01055 #define BILINEAR_ENLARGE(max, type, components) \
01056 { \
01057 \
01058 float k_y = 1.0 / scale_h; \
01059 float k_x = 1.0 / scale_w; \
01060 type **in_rows = (type**)input->get_rows(); \
01061 type **out_rows = (type**)output->get_rows(); \
01062 int out_h = pkg->out_row2 - pkg->out_row1; \
01063 int in_h_int = input->get_h(); \
01064 int in_w_int = input->get_w(); \
01065 int *table_int_x1, *table_int_y1; \
01066 int *table_int_x2, *table_int_y2; \
01067 float *table_frac_x_f, *table_antifrac_x_f, *table_frac_y_f, *table_antifrac_y_f; \
01068 int *table_frac_x_i, *table_antifrac_x_i, *table_frac_y_i, *table_antifrac_y_i; \
01069 \
01070 tabulate_blinear_f(table_int_x1, \
01071 table_int_x2, \
01072 table_frac_x_f, \
01073 table_antifrac_x_f, \
01074 k_x, \
01075 0, \
01076 out_w_int, \
01077 in_x1_int, \
01078 in_w_int); \
01079 tabulate_blinear_f(table_int_y1, \
01080 table_int_y2, \
01081 table_frac_y_f, \
01082 table_antifrac_y_f, \
01083 k_y, \
01084 pkg->out_row1, \
01085 pkg->out_row2, \
01086 in_y1_int, \
01087 in_h_int); \
01088 \
01089 for(int i = 0; i < out_h; i++) \
01090 { \
01091 int i_y1 = table_int_y1[i]; \
01092 int i_y2 = table_int_y2[i]; \
01093 float a_f; \
01094 float anti_a_f; \
01095 uint64_t a_i; \
01096 uint64_t anti_a_i; \
01097 a_f = table_frac_y_f[i]; \
01098 anti_a_f = table_antifrac_y_f[i]; \
01099 type *in_row1 = in_rows[i_y1]; \
01100 type *in_row2 = in_rows[i_y2]; \
01101 type *out_row = out_rows[i + pkg->out_row1]; \
01102 \
01103 for(int j = 0; j < out_w_int; j++) \
01104 { \
01105 int i_x1 = table_int_x1[j]; \
01106 int i_x2 = table_int_x2[j]; \
01107 float output1r, output1g, output1b, output1a; \
01108 float output2r, output2g, output2b, output2a; \
01109 float output3r, output3g, output3b, output3a; \
01110 float output4r, output4g, output4b, output4a; \
01111 float b_f; \
01112 float anti_b_f; \
01113 b_f = table_frac_x_f[j]; \
01114 anti_b_f = table_antifrac_x_f[j]; \
01115 \
01116 output1r = in_row1[i_x1 * components]; \
01117 output1g = in_row1[i_x1 * components + 1]; \
01118 output1b = in_row1[i_x1 * components + 2]; \
01119 if(components == 4) output1a = in_row1[i_x1 * components + 3]; \
01120 \
01121 output2r = in_row1[i_x2 * components]; \
01122 output2g = in_row1[i_x2 * components + 1]; \
01123 output2b = in_row1[i_x2 * components + 2]; \
01124 if(components == 4) output2a = in_row1[i_x2 * components + 3]; \
01125 \
01126 output3r = in_row2[i_x1 * components]; \
01127 output3g = in_row2[i_x1 * components + 1]; \
01128 output3b = in_row2[i_x1 * components + 2]; \
01129 if(components == 4) output3a = in_row2[i_x1 * components + 3]; \
01130 \
01131 output4r = in_row2[i_x2 * components]; \
01132 output4g = in_row2[i_x2 * components + 1]; \
01133 output4b = in_row2[i_x2 * components + 2]; \
01134 if(components == 4) output4a = in_row2[i_x2 * components + 3]; \
01135 \
01136 out_row[j * components] = \
01137 (type)(anti_a_f * (anti_b_f * output1r + \
01138 b_f * output2r) + \
01139 a_f * (anti_b_f * output3r + \
01140 b_f * output4r)); \
01141 out_row[j * components + 1] = \
01142 (type)(anti_a_f * (anti_b_f * output1g + \
01143 b_f * output2g) + \
01144 a_f * ((anti_b_f * output3g) + \
01145 b_f * output4g)); \
01146 out_row[j * components + 2] = \
01147 (type)(anti_a_f * ((anti_b_f * output1b) + \
01148 (b_f * output2b)) + \
01149 a_f * ((anti_b_f * output3b) + \
01150 b_f * output4b)); \
01151 if(components == 4) \
01152 out_row[j * components + 3] = \
01153 (type)(anti_a_f * ((anti_b_f * output1a) + \
01154 (b_f * output2a)) + \
01155 a_f * ((anti_b_f * output3a) + \
01156 b_f * output4a)); \
01157 } \
01158 } \
01159 \
01160 \
01161 delete [] table_int_x1; \
01162 delete [] table_int_x2; \
01163 delete [] table_int_y1; \
01164 delete [] table_int_y2; \
01165 delete [] table_frac_x_f; \
01166 delete [] table_antifrac_x_f; \
01167 delete [] table_frac_y_f; \
01168 delete [] table_antifrac_y_f; \
01169 \
01170 \
01171 }
01172
01173
01174 #define BICUBIC(max, type, components) \
01175 { \
01176 float k_y = 1.0 / scale_h; \
01177 float k_x = 1.0 / scale_w; \
01178 type **in_rows = (type**)input->get_rows(); \
01179 type **out_rows = (type**)output->get_rows(); \
01180 float *bspline_x_f, *bspline_y_f; \
01181 int *bspline_x_i, *bspline_y_i; \
01182 int *in_x_table, *in_y_table; \
01183 int in_h_int = input->get_h(); \
01184 int in_w_int = input->get_w(); \
01185 \
01186 tabulate_bcubic_f(bspline_x_f, \
01187 in_x_table, \
01188 k_x, \
01189 in_x1_int, \
01190 out_w_int, \
01191 in_w_int, \
01192 -1); \
01193 \
01194 tabulate_bcubic_f(bspline_y_f, \
01195 in_y_table, \
01196 k_y, \
01197 in_y1_int, \
01198 out_h_int, \
01199 in_h_int, \
01200 1); \
01201 \
01202 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
01203 { \
01204 for(int j = 0; j < out_w_int; j++) \
01205 { \
01206 int i_x = (int)(k_x * j); \
01207 float output1_f, output2_f, output3_f, output4_f; \
01208 uint64_t output1_i, output2_i, output3_i, output4_i; \
01209 output1_f = 0; \
01210 output2_f = 0; \
01211 output3_f = 0; \
01212 if(components == 4) \
01213 output4_f = 0; \
01214 int table_y = i * 4; \
01215 \
01216 \
01217 for(int m = -1; m < 3; m++) \
01218 { \
01219 float r1_f; \
01220 uint64_t r1_i; \
01221 r1_f = bspline_y_f[table_y]; \
01222 int y = in_y_table[table_y]; \
01223 int table_x = j * 4; \
01224 \
01225 for(int n = -1; n < 3; n++) \
01226 { \
01227 float r2_f; \
01228 uint64_t r2_i; \
01229 r2_f = bspline_x_f[table_x]; \
01230 int x = in_x_table[table_x]; \
01231 float r_square_f; \
01232 uint64_t r_square_i; \
01233 r_square_f = r1_f * r2_f; \
01234 output1_f += r_square_f * in_rows[y][x * components]; \
01235 output2_f += r_square_f * in_rows[y][x * components + 1]; \
01236 output3_f += r_square_f * in_rows[y][x * components + 2]; \
01237 if(components == 4) \
01238 output4_f += r_square_f * in_rows[y][x * components + 3]; \
01239 \
01240 table_x++; \
01241 } \
01242 table_y++; \
01243 } \
01244 \
01245 \
01246 out_rows[i][j * components] = (type)output1_f; \
01247 out_rows[i][j * components + 1] = (type)output2_f; \
01248 out_rows[i][j * components + 2] = (type)output3_f; \
01249 if(components == 4) \
01250 out_rows[i][j * components + 3] = (type)output4_f; \
01251 \
01252 } \
01253 } \
01254 \
01255 delete [] bspline_x_f; \
01256 delete [] bspline_y_f; \
01257 delete [] in_x_table; \
01258 delete [] in_y_table; \
01259 }
01260
01261
01262
01263
01264
01265 #define CUBE(x) ((x) * (x) * (x))
01266
01267 float ScaleUnit::cubic_bspline(float x)
01268 {
01269 float a, b, c, d;
01270
01271 if((x + 2.0F) <= 0.0F)
01272 {
01273 a = 0.0F;
01274 }
01275 else
01276 {
01277 a = CUBE(x + 2.0F);
01278 }
01279
01280
01281 if((x + 1.0F) <= 0.0F)
01282 {
01283 b = 0.0F;
01284 }
01285 else
01286 {
01287 b = CUBE(x + 1.0F);
01288 }
01289
01290 if(x <= 0)
01291 {
01292 c = 0.0F;
01293 }
01294 else
01295 {
01296 c = CUBE(x);
01297 }
01298
01299 if((x - 1.0F) <= 0.0F)
01300 {
01301 d = 0.0F;
01302 }
01303 else
01304 {
01305 d = CUBE(x - 1.0F);
01306 }
01307
01308
01309 return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
01310 }
01311
01312
01313 void ScaleUnit::tabulate_bcubic_f(float* &coef_table,
01314 int* &coord_table,
01315 float scale,
01316 int start,
01317 int pixels,
01318 int total_pixels,
01319 float coefficient)
01320 {
01321 coef_table = new float[pixels * 4];
01322 coord_table = new int[pixels * 4];
01323 for(int i = 0, j = 0; i < pixels; i++)
01324 {
01325 float f_x = (float)i * scale;
01326 float a = f_x - floor(f_x);
01327
01328 for(float m = -1; m < 3; m++)
01329 {
01330 coef_table[j] = cubic_bspline(coefficient * (m - a));
01331 coord_table[j] = (int)(start + (int)f_x + m);
01332 CLAMP(coord_table[j], 0, total_pixels - 1);
01333 j++;
01334 }
01335
01336 }
01337 }
01338
01339 void ScaleUnit::tabulate_bcubic_i(int* &coef_table,
01340 int* &coord_table,
01341 float scale,
01342 int start,
01343 int pixels,
01344 int total_pixels,
01345 float coefficient)
01346 {
01347 coef_table = new int[pixels * 4];
01348 coord_table = new int[pixels * 4];
01349 for(int i = 0, j = 0; i < pixels; i++)
01350 {
01351 float f_x = (float)i * scale;
01352 float a = f_x - floor(f_x);
01353
01354 for(float m = -1; m < 3; m++)
01355 {
01356 coef_table[j] = (int)(cubic_bspline(coefficient * (m - a)) * 0x10000);
01357 coord_table[j] = (int)(start + (int)f_x + m);
01358 CLAMP(coord_table[j], 0, total_pixels - 1);
01359 j++;
01360 }
01361
01362 }
01363 }
01364
01365 void ScaleUnit::tabulate_blinear_f(int* &table_int1,
01366 int* &table_int2,
01367 float* &table_frac,
01368 float* &table_antifrac,
01369 float scale,
01370 int pixel1,
01371 int pixel2,
01372 int start,
01373 int total_pixels)
01374 {
01375 table_int1 = new int[pixel2 - pixel1];
01376 table_int2 = new int[pixel2 - pixel1];
01377 table_frac = new float[pixel2 - pixel1];
01378 table_antifrac = new float[pixel2 - pixel1];
01379
01380 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
01381 {
01382 float f_x = (float)i * scale;
01383 int i_x = (int)floor(f_x);
01384 float a = (f_x - floor(f_x));
01385
01386 table_int1[j] = i_x + start;
01387 table_int2[j] = i_x + start + 1;
01388 CLAMP(table_int1[j], 0, total_pixels - 1);
01389 CLAMP(table_int2[j], 0, total_pixels - 1);
01390 table_frac[j] = a;
01391 table_antifrac[j] = 1.0F - a;
01392
01393 }
01394 }
01395
01396 void ScaleUnit::tabulate_blinear_i(int* &table_int1,
01397 int* &table_int2,
01398 int* &table_frac,
01399 int* &table_antifrac,
01400 float scale,
01401 int pixel1,
01402 int pixel2,
01403 int start,
01404 int total_pixels)
01405 {
01406 table_int1 = new int[pixel2 - pixel1];
01407 table_int2 = new int[pixel2 - pixel1];
01408 table_frac = new int[pixel2 - pixel1];
01409 table_antifrac = new int[pixel2 - pixel1];
01410
01411 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
01412 {
01413 double f_x = (float)i * scale;
01414 int i_x = (int)floor(f_x);
01415 float a = (f_x - floor(f_x));
01416
01417 table_int1[j] = i_x + start;
01418 table_int2[j] = i_x + start + 1;
01419 CLAMP(table_int1[j], 0, total_pixels - 1);
01420 CLAMP(table_int2[j], 0, total_pixels - 1);
01421 table_frac[j] = (int)(a * 0xffff);
01422 table_antifrac[j] = (int)((1.0F - a) * 0x10000);
01423
01424 }
01425 }
01426
01427 void ScaleUnit::process_package(LoadPackage *package)
01428 {
01429 ScalePackage *pkg = (ScalePackage*)package;
01430
01431
01432
01433 VFrame *output = engine->scale_output;
01434 VFrame *input = engine->scale_input;
01435 float scale_w = engine->w_scale;
01436 float scale_h = engine->h_scale;
01437 int in_x1_int = engine->in_x1_int;
01438 int in_y1_int = engine->in_y1_int;
01439 int out_h_int = engine->out_h_int;
01440 int out_w_int = engine->out_w_int;
01441 int do_yuv =
01442 (input->get_color_model() == BC_YUV888 ||
01443 input->get_color_model() == BC_YUVA8888 ||
01444 input->get_color_model() == BC_YUV161616 ||
01445 input->get_color_model() == BC_YUVA16161616);
01446
01447
01448 if(engine->interpolation_type == CUBIC_CUBIC ||
01449 (engine->interpolation_type == CUBIC_LINEAR
01450 && engine->w_scale > 1 &&
01451 engine->h_scale > 1))
01452 {
01453 switch(engine->scale_input->get_color_model())
01454 {
01455 case BC_RGB_FLOAT:
01456 BICUBIC(1.0, float, 3);
01457 break;
01458
01459 case BC_RGBA_FLOAT:
01460 BICUBIC(1.0, float, 4);
01461 break;
01462
01463 case BC_RGB888:
01464 case BC_YUV888:
01465 BICUBIC(0xff, unsigned char, 3);
01466 break;
01467
01468 case BC_RGBA8888:
01469 case BC_YUVA8888:
01470 BICUBIC(0xff, unsigned char, 4);
01471 break;
01472
01473 case BC_RGB161616:
01474 case BC_YUV161616:
01475 BICUBIC(0xffff, uint16_t, 3);
01476 break;
01477
01478 case BC_RGBA16161616:
01479 case BC_YUVA16161616:
01480 BICUBIC(0xffff, uint16_t, 4);
01481 break;
01482 }
01483 }
01484 else
01485
01486 if(engine->w_scale > 1 &&
01487 engine->h_scale > 1)
01488 {
01489 switch(engine->scale_input->get_color_model())
01490 {
01491 case BC_RGB_FLOAT:
01492 BILINEAR_ENLARGE(1.0, float, 3);
01493 break;
01494
01495 case BC_RGBA_FLOAT:
01496 BILINEAR_ENLARGE(1.0, float, 4);
01497 break;
01498
01499 case BC_RGB888:
01500 case BC_YUV888:
01501 BILINEAR_ENLARGE(0xff, unsigned char, 3);
01502 break;
01503
01504 case BC_RGBA8888:
01505 case BC_YUVA8888:
01506 BILINEAR_ENLARGE(0xff, unsigned char, 4);
01507 break;
01508
01509 case BC_RGB161616:
01510 case BC_YUV161616:
01511 BILINEAR_ENLARGE(0xffff, uint16_t, 3);
01512 break;
01513
01514 case BC_RGBA16161616:
01515 case BC_YUVA16161616:
01516 BILINEAR_ENLARGE(0xffff, uint16_t, 4);
01517 break;
01518 }
01519 }
01520 else
01521
01522 {
01523 switch(engine->scale_input->get_color_model())
01524 {
01525 case BC_RGB_FLOAT:
01526 BILINEAR_REDUCE(1.0, float, 3);
01527 break;
01528 case BC_RGBA_FLOAT:
01529 BILINEAR_REDUCE(1.0, float, 4);
01530 break;
01531 case BC_RGB888:
01532 case BC_YUV888:
01533 BILINEAR_REDUCE(0xff, unsigned char, 3);
01534 break;
01535
01536 case BC_RGBA8888:
01537 case BC_YUVA8888:
01538 BILINEAR_REDUCE(0xff, unsigned char, 4);
01539 break;
01540
01541 case BC_RGB161616:
01542 case BC_YUV161616:
01543 BILINEAR_REDUCE(0xffff, uint16_t, 3);
01544 break;
01545
01546 case BC_RGBA16161616:
01547 case BC_YUVA16161616:
01548 BILINEAR_REDUCE(0xffff, uint16_t, 4);
01549 break;
01550 }
01551 }
01552
01553
01554 }
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
01569 : LoadServer(cpus, cpus)
01570 {
01571 this->overlay = overlay;
01572 }
01573
01574 ScaleEngine::~ScaleEngine()
01575 {
01576 }
01577
01578 void ScaleEngine::init_packages()
01579 {
01580 for(int i = 0; i < total_packages; i++)
01581 {
01582 ScalePackage *package = (ScalePackage*)packages[i];
01583 package->out_row1 = out_h_int / total_packages * i;
01584 package->out_row2 = package->out_row1 + out_h_int / total_packages;
01585
01586 if(i >= total_packages - 1)
01587 package->out_row2 = out_h_int;
01588 }
01589 }
01590
01591 LoadClient* ScaleEngine::new_client()
01592 {
01593 return new ScaleUnit(this, overlay);
01594 }
01595
01596 LoadPackage* ScaleEngine::new_package()
01597 {
01598 return new ScalePackage;
01599 }
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613 TranslatePackage::TranslatePackage()
01614 {
01615 }
01616
01617
01618
01619 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
01620 : LoadClient(server)
01621 {
01622 this->overlay = overlay;
01623 this->engine = server;
01624 }
01625
01626 TranslateUnit::~TranslateUnit()
01627 {
01628 }
01629
01630
01631
01632 void TranslateUnit::translation_array_f(transfer_table_f* &table,
01633 float out_x1,
01634 float out_x2,
01635 float in_x1,
01636 float in_x2,
01637 int in_total,
01638 int out_total,
01639 int &out_x1_int,
01640 int &out_x2_int)
01641 {
01642 int out_w_int;
01643 float offset = out_x1 - in_x1;
01644
01645
01646 out_x1_int = (int)out_x1;
01647 out_x2_int = MIN((int)ceil(out_x2), out_total);
01648 out_w_int = out_x2_int - out_x1_int;
01649
01650 table = new transfer_table_f[out_w_int];
01651 bzero(table, sizeof(transfer_table_f) * out_w_int);
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663 float in_x = in_x1;
01664 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
01665 {
01666 transfer_table_f *entry = &table[out_x - out_x1_int];
01667
01668 entry->in_x1 = (int)in_x;
01669 entry->in_x2 = (int)in_x + 1;
01670
01671
01672 entry->output_fraction = 1;
01673
01674 if(out_x1 > out_x)
01675 {
01676 entry->output_fraction -= out_x1 - out_x;
01677 }
01678
01679 if(out_x2 < out_x + 1)
01680 {
01681 entry->output_fraction = (out_x2 - out_x);
01682 }
01683
01684
01685 float out_x_fraction = entry->output_fraction;
01686 float in_x_fraction = floor(in_x + 1) - in_x;
01687
01688 if(out_x_fraction <= in_x_fraction)
01689 {
01690 entry->in_fraction1 = out_x_fraction;
01691 entry->in_fraction2 = 0.0;
01692 in_x += out_x_fraction;
01693 }
01694 else
01695 {
01696 entry->in_fraction1 = in_x_fraction;
01697 in_x += out_x_fraction;
01698 entry->in_fraction2 = in_x - floor(in_x);
01699 }
01700
01701
01702 if(entry->in_x2 >= in_total)
01703 {
01704 entry->in_x2 = in_total - 1;
01705 entry->in_fraction2 = 0.0;
01706 }
01707
01708 if(entry->in_x1 >= in_total)
01709 {
01710 entry->in_x1 = in_total - 1;
01711 entry->in_fraction1 = 0.0;
01712 }
01713
01714
01715
01716
01717
01718
01719
01720 }
01721 }
01722
01723
01724 void TranslateUnit::translation_array_i(transfer_table_i* &table,
01725 float out_x1,
01726 float out_x2,
01727 float in_x1,
01728 float in_x2,
01729 int in_total,
01730 int out_total,
01731 int &out_x1_int,
01732 int &out_x2_int)
01733 {
01734 int out_w_int;
01735 float offset = out_x1 - in_x1;
01736
01737 out_x1_int = (int)out_x1;
01738 out_x2_int = MIN((int)ceil(out_x2), out_total);
01739 out_w_int = out_x2_int - out_x1_int;
01740
01741 table = new transfer_table_i[out_w_int];
01742 bzero(table, sizeof(transfer_table_i) * out_w_int);
01743
01744
01745
01746
01747 float in_x = in_x1;
01748 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
01749 {
01750 transfer_table_i *entry = &table[out_x - out_x1_int];
01751
01752 entry->in_x1 = (int)in_x;
01753 entry->in_x2 = (int)in_x + 1;
01754
01755
01756 entry->output_fraction = 0x10000;
01757
01758 if(out_x1 > out_x)
01759 {
01760 entry->output_fraction -= (int)((out_x1 - out_x) * 0x10000);
01761 }
01762
01763 if(out_x2 < out_x + 1)
01764 {
01765 entry->output_fraction = (int)((out_x2 - out_x) * 0x10000);
01766 }
01767
01768
01769 int out_x_fraction = entry->output_fraction;
01770 int in_x_fraction = (int)((floor(in_x + 1) - in_x) * 0x10000);
01771
01772 if(out_x_fraction <= in_x_fraction)
01773 {
01774 entry->in_fraction1 = out_x_fraction;
01775 entry->in_fraction2 = 0;
01776 in_x += (float)out_x_fraction / 0x10000;
01777 }
01778 else
01779 {
01780 entry->in_fraction1 = in_x_fraction;
01781 in_x += (float)out_x_fraction / 0x10000;
01782 entry->in_fraction2 = (int)((in_x - floor(in_x)) * 0x10000);
01783 }
01784
01785
01786 if(entry->in_x2 >= in_total)
01787 {
01788 entry->in_x2 = in_total - 1;
01789 entry->in_fraction2 = 0;
01790 }
01791
01792 if(entry->in_x1 >= in_total)
01793 {
01794 entry->in_x1 = in_total - 1;
01795 entry->in_fraction1 = 0;
01796 }
01797
01798
01799
01800
01801
01802
01803
01804 }
01805 }
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840 #define TRANSLATE(max, temp_type, type, components, chroma_offset) \
01841 { \
01842 \
01843 type **in_rows = (type**)input->get_rows(); \
01844 type **out_rows = (type**)output->get_rows(); \
01845 \
01846 \
01847 temp_type master_opacity; \
01848 if(sizeof(type) != 4) \
01849 master_opacity = (temp_type)(alpha * max + 0.5); \
01850 else \
01851 master_opacity = (temp_type)(alpha * max); \
01852 temp_type master_transparency = max - master_opacity; \
01853 float round = 0.0; \
01854 if(sizeof(type) != 4) \
01855 round = 0.5; \
01856 \
01857 \
01858 for(int i = row1; i < row2; i++) \
01859 { \
01860 int in_y1; \
01861 int in_y2; \
01862 float y_fraction1_f; \
01863 float y_fraction2_f; \
01864 float y_output_fraction_f; \
01865 in_y1 = y_table_f[i - out_y1_int].in_x1; \
01866 in_y2 = y_table_f[i - out_y1_int].in_x2; \
01867 y_fraction1_f = y_table_f[i - out_y1_int].in_fraction1; \
01868 y_fraction2_f = y_table_f[i - out_y1_int].in_fraction2; \
01869 y_output_fraction_f = y_table_f[i - out_y1_int].output_fraction; \
01870 type *in_row1 = in_rows[(in_y1)]; \
01871 type *in_row2 = in_rows[(in_y2)]; \
01872 type *out_row = out_rows[i]; \
01873 \
01874 for(int j = out_x1_int; j < out_x2_int; j++) \
01875 { \
01876 int in_x1; \
01877 int in_x2; \
01878 float x_fraction1_f; \
01879 float x_fraction2_f; \
01880 float x_output_fraction_f; \
01881 in_x1 = x_table_f[j - out_x1_int].in_x1; \
01882 in_x2 = x_table_f[j - out_x1_int].in_x2; \
01883 x_fraction1_f = x_table_f[j - out_x1_int].in_fraction1; \
01884 x_fraction2_f = x_table_f[j - out_x1_int].in_fraction2; \
01885 x_output_fraction_f = x_table_f[j - out_x1_int].output_fraction; \
01886 type *output = &out_row[j * components]; \
01887 temp_type input1, input2, input3, input4; \
01888 \
01889 float fraction1 = x_fraction1_f * y_fraction1_f; \
01890 float fraction2 = x_fraction2_f * y_fraction1_f; \
01891 float fraction3 = x_fraction1_f * y_fraction2_f; \
01892 float fraction4 = x_fraction2_f * y_fraction2_f; \
01893 \
01894 input1 = (type)(in_row1[in_x1 * components] * fraction1 + \
01895 in_row1[in_x2 * components] * fraction2 + \
01896 in_row2[in_x1 * components] * fraction3 + \
01897 in_row2[in_x2 * components] * fraction4 + round); \
01898 \
01899 \
01900 if(chroma_offset) \
01901 { \
01902 float extra_chroma = (1.0F - \
01903 fraction1 - \
01904 fraction2 - \
01905 fraction3 - \
01906 fraction4) * chroma_offset; \
01907 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
01908 in_row1[in_x2 * components + 1] * fraction2 + \
01909 in_row2[in_x1 * components + 1] * fraction3 + \
01910 in_row2[in_x2 * components + 1] * fraction4 + \
01911 extra_chroma + round); \
01912 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
01913 in_row1[in_x2 * components + 2] * fraction2 + \
01914 in_row2[in_x1 * components + 2] * fraction3 + \
01915 in_row2[in_x2 * components + 2] * fraction4 + \
01916 extra_chroma + round); \
01917 } \
01918 else \
01919 { \
01920 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
01921 in_row1[in_x2 * components + 1] * fraction2 + \
01922 in_row2[in_x1 * components + 1] * fraction3 + \
01923 in_row2[in_x2 * components + 1] * fraction4 + round); \
01924 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
01925 in_row1[in_x2 * components + 2] * fraction2 + \
01926 in_row2[in_x1 * components + 2] * fraction3 + \
01927 in_row2[in_x2 * components + 2] * fraction4 + round); \
01928 } \
01929 \
01930 if(components == 4) \
01931 input4 = (type)(in_row1[in_x1 * components + 3] * fraction1 + \
01932 in_row1[in_x2 * components + 3] * fraction2 + \
01933 in_row2[in_x1 * components + 3] * fraction3 + \
01934 in_row2[in_x2 * components + 3] * fraction4 + round); \
01935 \
01936 temp_type opacity; \
01937 if(sizeof(type) != 4) \
01938 opacity = (temp_type)(master_opacity * \
01939 y_output_fraction_f * \
01940 x_output_fraction_f + 0.5); \
01941 else \
01942 opacity = (temp_type)(master_opacity * \
01943 y_output_fraction_f * \
01944 x_output_fraction_f); \
01945 temp_type transparency = max - opacity; \
01946 \
01947 \
01948 \
01949 if(components == 3) \
01950 { \
01951 BLEND_3(max, temp_type, type, chroma_offset); \
01952 } \
01953 else \
01954 { \
01955 BLEND_4(max, temp_type, type, chroma_offset); \
01956 } \
01957 } \
01958 } \
01959 }
01960
01961 void TranslateUnit::process_package(LoadPackage *package)
01962 {
01963 TranslatePackage *pkg = (TranslatePackage*)package;
01964 int out_y1_int;
01965 int out_y2_int;
01966 int out_x1_int;
01967 int out_x2_int;
01968
01969
01970
01971 VFrame *input = engine->translate_input;
01972 VFrame *output = engine->translate_output;
01973 float in_x1 = engine->translate_in_x1;
01974 float in_y1 = engine->translate_in_y1;
01975 float in_x2 = engine->translate_in_x2;
01976 float in_y2 = engine->translate_in_y2;
01977 float out_x1 = engine->translate_out_x1;
01978 float out_y1 = engine->translate_out_y1;
01979 float out_x2 = engine->translate_out_x2;
01980 float out_y2 = engine->translate_out_y2;
01981 float alpha = engine->translate_alpha;
01982 int row1 = pkg->out_row1;
01983 int row2 = pkg->out_row2;
01984 int mode = engine->translate_mode;
01985 int in_total_x = input->get_w();
01986 int in_total_y = input->get_h();
01987 int do_yuv =
01988 (engine->translate_input->get_color_model() == BC_YUV888 ||
01989 engine->translate_input->get_color_model() == BC_YUVA8888 ||
01990 engine->translate_input->get_color_model() == BC_YUV161616 ||
01991 engine->translate_input->get_color_model() == BC_YUVA16161616);
01992
01993 transfer_table_f *x_table_f;
01994 transfer_table_f *y_table_f;
01995 transfer_table_i *x_table_i;
01996 transfer_table_i *y_table_i;
01997
01998 translation_array_f(x_table_f,
01999 out_x1,
02000 out_x2,
02001 in_x1,
02002 in_x2,
02003 in_total_x,
02004 output->get_w(),
02005 out_x1_int,
02006 out_x2_int);
02007 translation_array_f(y_table_f,
02008 out_y1,
02009 out_y2,
02010 in_y1,
02011 in_y2,
02012 in_total_y,
02013 output->get_h(),
02014 out_y1_int,
02015 out_y2_int);
02016
02017
02018
02019
02020 switch(engine->translate_input->get_color_model())
02021 {
02022 case BC_RGB888:
02023 TRANSLATE(0xff, uint32_t, unsigned char, 3, 0);
02024 break;
02025
02026 case BC_RGBA8888:
02027 TRANSLATE(0xff, uint32_t, unsigned char, 4, 0);
02028 break;
02029
02030 case BC_RGB_FLOAT:
02031 TRANSLATE(1.0, float, float, 3, 0);
02032 break;
02033
02034 case BC_RGBA_FLOAT:
02035 TRANSLATE(1.0, float, float, 4, 0);
02036 break;
02037
02038 case BC_RGB161616:
02039 TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
02040 break;
02041
02042 case BC_RGBA16161616:
02043 TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
02044 break;
02045
02046 case BC_YUV888:
02047 TRANSLATE(0xff, int32_t, unsigned char, 3, 0x80);
02048 break;
02049
02050 case BC_YUVA8888:
02051 TRANSLATE(0xff, int32_t, unsigned char, 4, 0x80);
02052 break;
02053
02054 case BC_YUV161616:
02055 TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
02056 break;
02057
02058 case BC_YUVA16161616:
02059 TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
02060 break;
02061 }
02062
02063
02064 delete [] x_table_f;
02065 delete [] y_table_f;
02066 }
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
02078 : LoadServer(cpus, cpus)
02079 {
02080 this->overlay = overlay;
02081 }
02082
02083 TranslateEngine::~TranslateEngine()
02084 {
02085 }
02086
02087 void TranslateEngine::init_packages()
02088 {
02089 int out_y1_int = (int)translate_out_y1;
02090 int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h());
02091 int out_h = out_y2_int - out_y1_int;
02092
02093 for(int i = 0; i < total_packages; i++)
02094 {
02095 TranslatePackage *package = (TranslatePackage*)packages[i];
02096 package->out_row1 = (int)(out_y1_int + out_h /
02097 total_packages *
02098 i);
02099 package->out_row2 = (int)((float)package->out_row1 +
02100 out_h /
02101 total_packages);
02102 if(i >= total_packages - 1)
02103 package->out_row2 = out_y2_int;
02104 }
02105 }
02106
02107 LoadClient* TranslateEngine::new_client()
02108 {
02109 return new TranslateUnit(this, overlay);
02110 }
02111
02112 LoadPackage* TranslateEngine::new_package()
02113 {
02114 return new TranslatePackage;
02115 }
02116
02117
02118
02119
02120
02121
02122
02123
02124 #define SCALE_TRANSLATE(max, temp_type, type, components, chroma_offset) \
02125 { \
02126 temp_type opacity; \
02127 if(sizeof(type) != 4) \
02128 opacity = (temp_type)(alpha * max + 0.5); \
02129 else \
02130 opacity = (temp_type)(alpha * max); \
02131 temp_type transparency = max - opacity; \
02132 \
02133 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02134 { \
02135 int in_y = y_table[i - out_y1]; \
02136 type *in_row = (type*)in_rows[in_y] + in_x1 * components; \
02137 type *output = (type*)out_rows[i] + out_x1 * components; \
02138 \
02139 \
02140 if(out_w != in_x2 - in_x1) \
02141 { \
02142 for(int j = 0; j < out_w; j++) \
02143 { \
02144 type *in_row_plus_x = in_row + x_table[j] * components; \
02145 temp_type input1, input2, input3, input4; \
02146 \
02147 input1 = in_row_plus_x[0]; \
02148 input2 = in_row_plus_x[1]; \
02149 input3 = in_row_plus_x[2]; \
02150 if(components == 4) \
02151 input4 = in_row_plus_x[3]; \
02152 \
02153 if(components == 3) \
02154 { \
02155 BLEND_3(max, temp_type, type, chroma_offset); \
02156 } \
02157 else \
02158 { \
02159 BLEND_4(max, temp_type, type, chroma_offset); \
02160 } \
02161 output += components; \
02162 } \
02163 } \
02164 else \
02165 \
02166 { \
02167 for(int j = 0; j < out_w; j++) \
02168 { \
02169 temp_type input1, input2, input3, input4; \
02170 \
02171 input1 = in_row[0]; \
02172 input2 = in_row[1]; \
02173 input3 = in_row[2]; \
02174 if(components == 4) \
02175 input4 = in_row[3]; \
02176 \
02177 if(components == 3) \
02178 { \
02179 BLEND_3(max, temp_type, type, chroma_offset); \
02180 } \
02181 else \
02182 { \
02183 BLEND_4(max, temp_type, type, chroma_offset); \
02184 } \
02185 in_row += components; \
02186 output += components; \
02187 } \
02188 } \
02189 } \
02190 }
02191
02192
02193
02194 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
02195 : LoadClient(server)
02196 {
02197 this->overlay = overlay;
02198 this->scale_translate = server;
02199 }
02200
02201 ScaleTranslateUnit::~ScaleTranslateUnit()
02202 {
02203 }
02204
02205 void ScaleTranslateUnit::scale_array(int* &table,
02206 int out_x1,
02207 int out_x2,
02208 int in_x1,
02209 int in_x2,
02210 int is_x)
02211 {
02212 float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
02213
02214 table = new int[out_x2 - out_x1];
02215
02216 if(!is_x)
02217 {
02218 for(int i = 0; i < out_x2 - out_x1; i++)
02219 {
02220 table[i] = (int)((float)i / scale + in_x1);
02221 }
02222 }
02223 else
02224 {
02225 for(int i = 0; i < out_x2 - out_x1; i++)
02226 {
02227 table[i] = (int)((float)i / scale);
02228 }
02229 }
02230 }
02231
02232
02233 void ScaleTranslateUnit::process_package(LoadPackage *package)
02234 {
02235 ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
02236
02237
02238 VFrame *output = scale_translate->output;
02239 VFrame *input = scale_translate->input;
02240 int in_x1 = scale_translate->in_x1;
02241 int in_y1 = scale_translate->in_y1;
02242 int in_x2 = scale_translate->in_x2;
02243 int in_y2 = scale_translate->in_y2;
02244 int out_x1 = scale_translate->out_x1;
02245 int out_y1 = scale_translate->out_y1;
02246 int out_x2 = scale_translate->out_x2;
02247 int out_y2 = scale_translate->out_y2;
02248 float alpha = scale_translate->alpha;
02249 int mode = scale_translate->mode;
02250 int out_w = out_x2 - out_x1;
02251
02252 int *x_table;
02253 int *y_table;
02254 unsigned char **in_rows = input->get_rows();
02255 unsigned char **out_rows = output->get_rows();
02256
02257
02258
02259
02260 if(out_w != in_x2 - in_x1)
02261 {
02262 scale_array(x_table,
02263 out_x1,
02264 out_x2,
02265 in_x1,
02266 in_x2,
02267 1);
02268 }
02269 scale_array(y_table,
02270 out_y1,
02271 out_y2,
02272 in_y1,
02273 in_y2,
02274 0);
02275
02276
02277 if (mode == TRANSFER_REPLACE && (out_w == in_x2 - in_x1))
02278 {
02279
02280 char bytes_per_pixel = input->calculate_bytes_per_pixel(input->get_color_model());
02281 int line_len = out_w * bytes_per_pixel;
02282 int in_start_byte = in_x1 * bytes_per_pixel;
02283 int out_start_byte = out_x1 * bytes_per_pixel;
02284 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02285 {
02286 memcpy (out_rows[i] + out_start_byte,
02287 in_rows[y_table[i - out_y1]] + in_start_byte ,
02288 line_len);
02289 }
02290
02291 }
02292 else
02293 switch(input->get_color_model())
02294 {
02295 case BC_RGB888:
02296 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 3, 0);
02297 break;
02298
02299 case BC_RGB_FLOAT:
02300 SCALE_TRANSLATE(1.0, float, float, 3, 0);
02301 break;
02302
02303 case BC_YUV888:
02304 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 3, 0x80);
02305 break;
02306
02307 case BC_RGBA8888:
02308 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 4, 0);
02309 break;
02310
02311 case BC_RGBA_FLOAT:
02312 SCALE_TRANSLATE(1.0, float, float, 4, 0);
02313 break;
02314
02315 case BC_YUVA8888:
02316 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 4, 0x80);
02317 break;
02318
02319
02320 case BC_RGB161616:
02321 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
02322 break;
02323
02324 case BC_YUV161616:
02325 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
02326 break;
02327
02328 case BC_RGBA16161616:
02329 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
02330 break;
02331
02332 case BC_YUVA16161616:
02333 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
02334 break;
02335 }
02336
02337
02338 if(out_x2 - out_x1 != in_x2 - in_x1)
02339 delete [] x_table;
02340 delete [] y_table;
02341
02342 };
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
02353 : LoadServer(cpus, cpus)
02354 {
02355 this->overlay = overlay;
02356 }
02357
02358 ScaleTranslateEngine::~ScaleTranslateEngine()
02359 {
02360 }
02361
02362 void ScaleTranslateEngine::init_packages()
02363 {
02364 int out_h = out_y2 - out_y1;
02365
02366 for(int i = 0; i < total_packages; i++)
02367 {
02368 ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i];
02369 package->out_row1 = (int)(out_y1 + out_h /
02370 total_packages *
02371 i);
02372 package->out_row2 = (int)((float)package->out_row1 +
02373 out_h /
02374 total_packages);
02375 if(i >= total_packages - 1)
02376 package->out_row2 = out_y2;
02377 }
02378 }
02379
02380 LoadClient* ScaleTranslateEngine::new_client()
02381 {
02382 return new ScaleTranslateUnit(this, overlay);
02383 }
02384
02385 LoadPackage* ScaleTranslateEngine::new_package()
02386 {
02387 return new ScaleTranslatePackage;
02388 }
02389
02390
02391 ScaleTranslatePackage::ScaleTranslatePackage()
02392 {
02393 }
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422 #define BLEND_ONLY(temp_type, type, max, components, chroma_offset) \
02423 { \
02424 temp_type opacity; \
02425 if(sizeof(type) != 4) \
02426 opacity = (temp_type)(alpha * max + 0.5); \
02427 else \
02428 opacity = (temp_type)(alpha * max); \
02429 temp_type transparency = max - opacity; \
02430 \
02431 type** output_rows = (type**)output->get_rows(); \
02432 type** input_rows = (type**)input->get_rows(); \
02433 int w = input->get_w(); \
02434 int h = input->get_h(); \
02435 \
02436 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02437 { \
02438 type* in_row = input_rows[i]; \
02439 type* output = output_rows[i]; \
02440 \
02441 for(int j = 0; j < w; j++) \
02442 { \
02443 temp_type input1, input2, input3, input4; \
02444 input1 = in_row[0]; \
02445 input2 = in_row[1]; \
02446 input3 = in_row[2]; \
02447 if(components == 4) input4 = in_row[3]; \
02448 \
02449 \
02450 if(components == 3) \
02451 { \
02452 BLEND_3(max, temp_type, type, chroma_offset); \
02453 } \
02454 else \
02455 { \
02456 BLEND_4(max, temp_type, type, chroma_offset); \
02457 } \
02458 \
02459 in_row += components; \
02460 output += components; \
02461 } \
02462 } \
02463 }
02464
02465
02466 #define BLEND_ONLY_TRANSFER_REPLACE(type, components) \
02467 { \
02468 \
02469 type** output_rows = (type**)output->get_rows(); \
02470 type** input_rows = (type**)input->get_rows(); \
02471 int w = input->get_w(); \
02472 int h = input->get_h(); \
02473 int line_len = w * sizeof(type) * components; \
02474 \
02475 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02476 { \
02477 memcpy(output_rows[i], input_rows[i], line_len); \
02478 } \
02479 }
02480
02481
02482 #define BLEND_ONLY_4_NORMAL(temp_type, type, max, chroma_offset) \
02483 { \
02484 temp_type opacity = (temp_type)(alpha * max + 0.5); \
02485 temp_type transparency = max - opacity; \
02486 temp_type max_squared = ((temp_type)max) * max; \
02487 \
02488 type** output_rows = (type**)output->get_rows(); \
02489 type** input_rows = (type**)input->get_rows(); \
02490 int w = input->get_w(); \
02491 int h = input->get_h(); \
02492 \
02493 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02494 { \
02495 type* in_row = input_rows[i]; \
02496 type* output = output_rows[i]; \
02497 \
02498 for(int j = 0; j < w; j++) \
02499 { \
02500 temp_type pixel_opacity, pixel_transparency; \
02501 pixel_opacity = opacity * in_row[3]; \
02502 pixel_transparency = (temp_type)max_squared - pixel_opacity; \
02503 \
02504 \
02505 temp_type r,g,b; \
02506 output[0] = ((temp_type)in_row[0] * pixel_opacity + \
02507 (temp_type)output[0] * pixel_transparency) / max / max; \
02508 output[1] = (((temp_type)in_row[1] - chroma_offset) * pixel_opacity + \
02509 ((temp_type)output[1] - chroma_offset) * pixel_transparency) \
02510 / max / max + \
02511 chroma_offset; \
02512 output[2] = (((temp_type)in_row[2] - chroma_offset) * pixel_opacity + \
02513 ((temp_type)output[2] - chroma_offset) * pixel_transparency) \
02514 / max / max + \
02515 chroma_offset; \
02516 output[3] = (type)(in_row[3] > output[3] ? in_row[3] : output[3]); \
02517 \
02518 in_row += 4; \
02519 output += 4; \
02520 } \
02521 } \
02522 }
02523
02524
02525
02526
02527 #define BLEND_ONLY_3_NORMAL(temp_type, type, max, chroma_offset) \
02528 { \
02529 const int bits = sizeof(type) * 8; \
02530 temp_type opacity = (temp_type)(alpha * ((temp_type)1 << bits) + 0.5); \
02531 temp_type transparency = ((temp_type)1 << bits) - opacity; \
02532 \
02533 type** output_rows = (type**)output->get_rows(); \
02534 type** input_rows = (type**)input->get_rows(); \
02535 int w = input->get_w() * 3; \
02536 int h = input->get_h(); \
02537 \
02538 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02539 { \
02540 type* in_row = input_rows[i]; \
02541 type* output = output_rows[i]; \
02542 \
02543 for(int j = 0; j < w; j++) \
02544 { \
02545 *output = ((temp_type)*in_row * opacity + *output * transparency) >> bits; \
02546 in_row ++; \
02547 output ++; \
02548 } \
02549 } \
02550 }
02551
02552
02553
02554 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
02555 : LoadClient(server)
02556 {
02557 this->overlay = overlay;
02558 this->blend_engine = server;
02559 }
02560
02561 BlendUnit::~BlendUnit()
02562 {
02563 }
02564
02565 void BlendUnit::process_package(LoadPackage *package)
02566 {
02567 BlendPackage *pkg = (BlendPackage*)package;
02568
02569
02570 VFrame *output = blend_engine->output;
02571 VFrame *input = blend_engine->input;
02572 float alpha = blend_engine->alpha;
02573 int mode = blend_engine->mode;
02574
02575 if (mode == TRANSFER_REPLACE)
02576 {
02577 switch(input->get_color_model())
02578 {
02579 case BC_RGB_FLOAT:
02580 BLEND_ONLY_TRANSFER_REPLACE(float, 3);
02581 break;
02582 case BC_RGBA_FLOAT:
02583 BLEND_ONLY_TRANSFER_REPLACE(float, 4);
02584 break;
02585 case BC_RGB888:
02586 case BC_YUV888:
02587 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 3);
02588 break;
02589 case BC_RGBA8888:
02590 case BC_YUVA8888:
02591 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 4);
02592 break;
02593 case BC_RGB161616:
02594 case BC_YUV161616:
02595 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 3);
02596 break;
02597 case BC_RGBA16161616:
02598 case BC_YUVA16161616:
02599 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 4);
02600 break;
02601 }
02602 }
02603 else
02604 if (mode == TRANSFER_NORMAL)
02605 {
02606 switch(input->get_color_model())
02607 {
02608 case BC_RGB_FLOAT:
02609 {
02610 float opacity = alpha;
02611 float transparency = 1.0 - alpha;
02612
02613 float** output_rows = (float**)output->get_rows();
02614 float** input_rows = (float**)input->get_rows();
02615 int w = input->get_w() * 3;
02616 int h = input->get_h();
02617
02618 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02619 {
02620 float* in_row = input_rows[i];
02621 float* output = output_rows[i];
02622
02623 for(int j = 0; j < w; j++)
02624 {
02625 *output = *in_row * opacity + *output * transparency;
02626 in_row++;
02627 output++;
02628 }
02629 }
02630 break;
02631 }
02632 case BC_RGBA_FLOAT:
02633 {
02634 float opacity = alpha;
02635 float transparency = 1.0 - alpha;
02636
02637 float** output_rows = (float**)output->get_rows();
02638 float** input_rows = (float**)input->get_rows();
02639 int w = input->get_w();
02640 int h = input->get_h();
02641
02642 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02643 {
02644 float* in_row = input_rows[i];
02645 float* output = output_rows[i];
02646
02647 for(int j = 0; j < w; j++)
02648 {
02649 float pixel_opacity, pixel_transparency;
02650 pixel_opacity = opacity * in_row[3];
02651 pixel_transparency = 1.0 - pixel_opacity;
02652
02653
02654 output[0] = in_row[0] * pixel_opacity +
02655 output[0] * pixel_transparency;
02656 output[1] = in_row[1] * pixel_opacity +
02657 output[1] * pixel_transparency;
02658 output[2] = in_row[2] * pixel_opacity +
02659 output[2] * pixel_transparency;
02660 output[3] = in_row[3] > output[3] ? in_row[3] : output[3];
02661
02662 in_row += 4;
02663 output += 4;
02664 }
02665 }
02666 break;
02667 }
02668 case BC_RGB888:
02669 BLEND_ONLY_3_NORMAL(uint32_t, unsigned char, 0xff, 0);
02670 break;
02671 case BC_YUV888:
02672 BLEND_ONLY_3_NORMAL(int32_t, unsigned char, 0xff, 0x80);
02673 break;
02674 case BC_RGBA8888:
02675 BLEND_ONLY_4_NORMAL(uint32_t, unsigned char, 0xff, 0);
02676 break;
02677 case BC_YUVA8888:
02678 BLEND_ONLY_4_NORMAL(int32_t, unsigned char, 0xff, 0x80);
02679 break;
02680 case BC_RGB161616:
02681 BLEND_ONLY_3_NORMAL(uint64_t, uint16_t, 0xffff, 0);
02682 break;
02683 case BC_YUV161616:
02684 BLEND_ONLY_3_NORMAL(int64_t, uint16_t, 0xffff, 0x8000);
02685 break;
02686 case BC_RGBA16161616:
02687 BLEND_ONLY_4_NORMAL(uint64_t, uint16_t, 0xffff, 0);
02688 break;
02689 case BC_YUVA16161616:
02690 BLEND_ONLY_4_NORMAL(int64_t, uint16_t, 0xffff, 0x8000);
02691 break;
02692 }
02693 }
02694 else
02695 switch(input->get_color_model())
02696 {
02697 case BC_RGB_FLOAT:
02698 BLEND_ONLY(float, float, 1.0, 3, 0);
02699 break;
02700 case BC_RGBA_FLOAT:
02701 BLEND_ONLY(float, float, 1.0, 4, 0);
02702 break;
02703 case BC_RGB888:
02704 BLEND_ONLY(uint32_t, unsigned char, 0xff, 3, 0);
02705 break;
02706 case BC_YUV888:
02707 BLEND_ONLY(int32_t, unsigned char, 0xff, 3, 0x80);
02708 break;
02709 case BC_RGBA8888:
02710 BLEND_ONLY(uint32_t, unsigned char, 0xff, 4, 0);
02711 break;
02712 case BC_YUVA8888:
02713 BLEND_ONLY(int32_t, unsigned char, 0xff, 4, 0x80);
02714 break;
02715 case BC_RGB161616:
02716 BLEND_ONLY(uint64_t, uint16_t, 0xffff, 3, 0);
02717 break;
02718 case BC_YUV161616:
02719 BLEND_ONLY(int64_t, uint16_t, 0xffff, 3, 0x8000);
02720 break;
02721 case BC_RGBA16161616:
02722 BLEND_ONLY(uint64_t, uint16_t, 0xffff, 4, 0);
02723 break;
02724 case BC_YUVA16161616:
02725 BLEND_ONLY(int64_t, uint16_t, 0xffff, 4, 0x8000);
02726 break;
02727 }
02728 }
02729
02730
02731
02732 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
02733 : LoadServer(cpus, cpus)
02734 {
02735 this->overlay = overlay;
02736 }
02737
02738 BlendEngine::~BlendEngine()
02739 {
02740 }
02741
02742 void BlendEngine::init_packages()
02743 {
02744 for(int i = 0; i < total_packages; i++)
02745 {
02746 BlendPackage *package = (BlendPackage*)packages[i];
02747 package->out_row1 = (int)(input->get_h() /
02748 total_packages *
02749 i);
02750 package->out_row2 = (int)((float)package->out_row1 +
02751 input->get_h() /
02752 total_packages);
02753
02754 if(i >= total_packages - 1)
02755 package->out_row2 = input->get_h();
02756 }
02757 }
02758
02759 LoadClient* BlendEngine::new_client()
02760 {
02761 return new BlendUnit(this, overlay);
02762 }
02763
02764 LoadPackage* BlendEngine::new_package()
02765 {
02766 return new BlendPackage;
02767 }
02768
02769
02770 BlendPackage::BlendPackage()
02771 {
02772 }
02773
02774