00001 #include "bcsignals.h"
00002 #include "condition.h"
00003 #include "clip.h"
00004 #include "maskauto.h"
00005 #include "maskautos.h"
00006 #include "maskengine.h"
00007 #include "mutex.h"
00008 #include "vframe.h"
00009
00010 #include <math.h>
00011 #include <stdint.h>
00012 #include <string.h>
00013 #include <limits.h>
00014
00015 #include "feather.h"
00016
00017
00018 int64_t get_difference(struct timeval *start_time)
00019 {
00020 struct timeval new_time;
00021
00022 gettimeofday(&new_time, 0);
00023
00024 new_time.tv_usec -= start_time->tv_usec;
00025 new_time.tv_sec -= start_time->tv_sec;
00026 if(new_time.tv_usec < 0)
00027 {
00028 new_time.tv_usec += 1000000;
00029 new_time.tv_sec--;
00030 }
00031
00032 return (int64_t)new_time.tv_sec * 1000000 +
00033 (int64_t)new_time.tv_usec;
00034
00035 }
00036
00037
00038
00039 MaskPackage::MaskPackage()
00040 {
00041 }
00042
00043 MaskPackage::~MaskPackage()
00044 {
00045 }
00046
00047
00048
00049
00050
00051 MaskUnit::MaskUnit(MaskEngine *engine)
00052 : LoadClient(engine)
00053 {
00054 this->engine = engine;
00055 row_spans_h = 0;
00056 row_spans = 0;
00057 }
00058
00059
00060 MaskUnit::~MaskUnit()
00061 {
00062 if (row_spans)
00063 {
00064 for (int i = 0; i < row_spans_h; i++)
00065 free(row_spans[i]);
00066 delete [] row_spans;
00067 }
00068 }
00069
00070 #ifndef SQR
00071 #define SQR(x) ((x) * (x))
00072 #endif
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 inline void MaskUnit::draw_line_clamped(
00090 int draw_x1,
00091 int draw_y1,
00092 int draw_x2,
00093 int draw_y2,
00094 int w,
00095 int h,
00096 int hoffset)
00097 {
00098
00099 if (draw_y1 == draw_y2) return;
00100
00101 if(draw_y2 < draw_y1)
00102 {
00103 int tmp;
00104 tmp = draw_x1;
00105 draw_x1 = draw_x2;
00106 draw_x2 = tmp;
00107 tmp = draw_y1;
00108 draw_y1 = draw_y2;
00109 draw_y2 = tmp;
00110 }
00111
00112 float slope = ((float)draw_x2 - draw_x1) / ((float)draw_y2 - draw_y1);
00113 w--;
00114 for(int y_i = draw_y1; y_i < draw_y2; y_i++)
00115 {
00116 if (y_i >= h)
00117 return;
00118 else if(y_i >= 0)
00119 {
00120 int x = (int)(slope * (y_i - draw_y1) + draw_x1);
00121 int x_i = CLIP(x, 0, w);
00122
00123
00124 short *span = row_spans[y_i + hoffset];
00125 if (span[0] >= span[1]) {
00126 span[1] *= 2;
00127 span = row_spans[y_i + hoffset] = (short *) realloc (span, span[1] * sizeof(short));
00128 };
00129
00130 short index = 2;
00131 while (index < span[0] && span[index] < x_i)
00132 index++;
00133 for (int j = span[0]; j > index; j--) {
00134 span[j] = span[j-1];
00135 }
00136 span[index] = x_i;
00137 span[0] ++;
00138 }
00139 }
00140 }
00141
00142 template<class T>
00143 void MaskUnit::blur_strip(float *val_p,
00144 float *val_m,
00145 float *dst,
00146 float *src,
00147 int size,
00148 T max)
00149 {
00150 float *sp_p = src;
00151 float *sp_m = src + size - 1;
00152 float *vp = val_p;
00153 float *vm = val_m + size - 1;
00154 float initial_p = sp_p[0];
00155 float initial_m = sp_m[0];
00156
00157
00158 for(int k = 0; k < size; k++)
00159 {
00160 int terms = (k < 4) ? k : 4;
00161 int l;
00162 for(l = 0; l <= terms; l++)
00163 {
00164 *vp += n_p[l] * sp_p[-l] - d_p[l] * vp[-l];
00165 *vm += n_m[l] * sp_m[l] - d_m[l] * vm[l];
00166 }
00167
00168 for( ; l <= 4; l++)
00169 {
00170 *vp += (n_p[l] - bd_p[l]) * initial_p;
00171 *vm += (n_m[l] - bd_m[l]) * initial_m;
00172 }
00173 sp_p++;
00174 sp_m--;
00175 vp++;
00176 vm--;
00177 }
00178
00179 for(int i = 0; i < size; i++)
00180 {
00181 float sum = val_p[i] + val_m[i];
00182 CLAMP(sum, 0, max);
00183 dst[i] = sum;
00184 }
00185 }
00186
00187
00188
00189 int MaskUnit::do_feather_2(VFrame *output,
00190 VFrame *input,
00191 float feather,
00192 int start_out,
00193 int end_out)
00194 {
00195
00196 int fint = (int)feather;
00197 DO_FEATHER_N(unsigned char, uint32_t, 0xffff, fint);
00198
00199 }
00200
00201
00202 void MaskUnit::do_feather(VFrame *output,
00203 VFrame *input,
00204 float feather,
00205 int start_out,
00206 int end_out)
00207 {
00208
00209
00210 double constants[8];
00211 double div;
00212 double std_dev = sqrt(-(double)(feather * feather) / (2 * log(1.0 / 255.0)));
00213 div = sqrt(2 * M_PI) * std_dev;
00214 constants[0] = -1.783 / std_dev;
00215 constants[1] = -1.723 / std_dev;
00216 constants[2] = 0.6318 / std_dev;
00217 constants[3] = 1.997 / std_dev;
00218 constants[4] = 1.6803 / div;
00219 constants[5] = 3.735 / div;
00220 constants[6] = -0.6803 / div;
00221 constants[7] = -0.2598 / div;
00222
00223 n_p[0] = constants[4] + constants[6];
00224 n_p[1] = exp(constants[1]) *
00225 (constants[7] * sin(constants[3]) -
00226 (constants[6] + 2 * constants[4]) * cos(constants[3])) +
00227 exp(constants[0]) *
00228 (constants[5] * sin(constants[2]) -
00229 (2 * constants[6] + constants[4]) * cos(constants[2]));
00230
00231 n_p[2] = 2 * exp(constants[0] + constants[1]) *
00232 ((constants[4] + constants[6]) * cos(constants[3]) *
00233 cos(constants[2]) - constants[5] *
00234 cos(constants[3]) * sin(constants[2]) -
00235 constants[7] * cos(constants[2]) * sin(constants[3])) +
00236 constants[6] * exp(2 * constants[0]) +
00237 constants[4] * exp(2 * constants[1]);
00238
00239 n_p[3] = exp(constants[1] + 2 * constants[0]) *
00240 (constants[7] * sin(constants[3]) -
00241 constants[6] * cos(constants[3])) +
00242 exp(constants[0] + 2 * constants[1]) *
00243 (constants[5] * sin(constants[2]) - constants[4] *
00244 cos(constants[2]));
00245 n_p[4] = 0.0;
00246
00247 d_p[0] = 0.0;
00248 d_p[1] = -2 * exp(constants[1]) * cos(constants[3]) -
00249 2 * exp(constants[0]) * cos(constants[2]);
00250
00251 d_p[2] = 4 * cos(constants[3]) * cos(constants[2]) *
00252 exp(constants[0] + constants[1]) +
00253 exp(2 * constants[1]) + exp (2 * constants[0]);
00254
00255 d_p[3] = -2 * cos(constants[2]) * exp(constants[0] + 2 * constants[1]) -
00256 2 * cos(constants[3]) * exp(constants[1] + 2 * constants[0]);
00257
00258 d_p[4] = exp(2 * constants[0] + 2 * constants[1]);
00259
00260 for(int i = 0; i < 5; i++) d_m[i] = d_p[i];
00261
00262 n_m[0] = 0.0;
00263 for(int i = 1; i <= 4; i++)
00264 n_m[i] = n_p[i] - d_p[i] * n_p[0];
00265
00266 double sum_n_p, sum_n_m, sum_d;
00267 double a, b;
00268
00269 sum_n_p = 0.0;
00270 sum_n_m = 0.0;
00271 sum_d = 0.0;
00272 for(int i = 0; i < 5; i++)
00273 {
00274 sum_n_p += n_p[i];
00275 sum_n_m += n_m[i];
00276 sum_d += d_p[i];
00277 }
00278
00279 a = sum_n_p / (1 + sum_d);
00280 b = sum_n_m / (1 + sum_d);
00281
00282 for(int i = 0; i < 5; i++)
00283 {
00284 bd_p[i] = d_p[i] * a;
00285 bd_m[i] = d_m[i] * b;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 #define DO_FEATHER(type, max) \
00310 { \
00311 int frame_w = input->get_w(); \
00312 int frame_h = input->get_h(); \
00313 int size = MAX(frame_w, frame_h); \
00314 float *src = new float[size]; \
00315 float *dst = new float[size]; \
00316 float *val_p = new float[size]; \
00317 float *val_m = new float[size]; \
00318 int start_in = start_out - (int)feather; \
00319 int end_in = end_out + (int)feather; \
00320 if(start_in < 0) start_in = 0; \
00321 if(end_in > frame_h) end_in = frame_h; \
00322 int strip_size = end_in - start_in; \
00323 type **in_rows = (type**)input->get_rows(); \
00324 type **out_rows = (type**)output->get_rows(); \
00325 int j; \
00326 \
00327 \
00328 for(j = 0; j < frame_w; j++) \
00329 { \
00330 \
00331 bzero(val_p, sizeof(float) * (end_in - start_in)); \
00332 bzero(val_m, sizeof(float) * (end_in - start_in)); \
00333 for(int l = 0, k = start_in; k < end_in; l++, k++) \
00334 { \
00335 src[l] = (float)in_rows[k][j]; \
00336 } \
00337 \
00338 blur_strip(val_p, val_m, dst, src, strip_size, max); \
00339 \
00340 for(int l = start_out - start_in, k = start_out; k < end_out; l++, k++) \
00341 { \
00342 out_rows[k][j] = (type)dst[l]; \
00343 } \
00344 } \
00345 \
00346 for(j = start_out; j < end_out; j++) \
00347 { \
00348 \
00349 bzero(val_p, sizeof(float) * frame_w); \
00350 bzero(val_m, sizeof(float) * frame_w); \
00351 for(int k = 0; k < frame_w; k++) \
00352 { \
00353 src[k] = (float)out_rows[j][k]; \
00354 } \
00355 \
00356 blur_strip(val_p, val_m, dst, src, frame_w, max); \
00357 \
00358 for(int k = 0; k < frame_w; k++) \
00359 { \
00360 out_rows[j][k] = (type)dst[k]; \
00361 } \
00362 } \
00363 \
00364 \
00365 \
00366 delete [] src; \
00367 delete [] dst; \
00368 delete [] val_p; \
00369 delete [] val_m; \
00370 \
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 switch(input->get_color_model())
00382 {
00383 case BC_A8:
00384 DO_FEATHER(unsigned char, 0xff);
00385 break;
00386
00387 case BC_A16:
00388 DO_FEATHER(uint16_t, 0xffff);
00389 break;
00390
00391 case BC_A_FLOAT:
00392 DO_FEATHER(float, 1.0f);
00393 break;
00394 }
00395
00396
00397
00398
00399 }
00400
00401 void MaskUnit::process_package(LoadPackage *package)
00402 {
00403 MaskPackage *ptr = (MaskPackage*)package;
00404
00405 int start_row = SHRT_MIN;
00406 int end_row;
00407 if(engine->recalculate)
00408 {
00409 VFrame *mask;
00410 if(engine->feather > 0)
00411 mask = engine->temp_mask;
00412 else
00413 mask = engine->mask;
00414
00415 SET_TRACE
00416
00417 int mask_w = mask->get_w();
00418 int mask_h = mask->get_h();
00419 int mask_color_model = mask->get_color_model();
00420 int oversampled_package_w = mask_w * OVERSAMPLE;
00421 int oversampled_package_h = (ptr->row2 - ptr->row1) * OVERSAMPLE;
00422
00423
00424 SET_TRACE
00425
00426 int local_first_nonempty_rowspan = SHRT_MIN;
00427 int local_last_nonempty_rowspan = SHRT_MIN;
00428
00429 if (!row_spans || row_spans_h != mask_h * OVERSAMPLE) {
00430 int i;
00431 if (row_spans) {
00432 for (i = 0; i < row_spans_h; i++)
00433 free(row_spans[i]);
00434 delete [] row_spans;
00435 }
00436 row_spans_h = mask_h * OVERSAMPLE;
00437 row_spans = new short *[mask_h * OVERSAMPLE];
00438 for (i= 0; i<mask_h * OVERSAMPLE; i++) {
00439
00440 row_spans[i] = (short *)malloc(sizeof(short) * NUM_SPANS);
00441
00442 row_spans[i][1] = NUM_SPANS;
00443 }
00444 }
00445
00446 SET_TRACE
00447
00448
00449 SET_TRACE
00450
00451
00452
00453
00454
00455 for(int k = 0; k < engine->point_sets.total; k++)
00456 {
00457 int old_x, old_y;
00458 old_x = SHRT_MIN;
00459 ArrayList<MaskPoint*> *points = engine->point_sets.values[k];
00460
00461 if(points->total < 2) continue;
00462
00463 for (int i = ptr->row1 * OVERSAMPLE; i < ptr->row2 * OVERSAMPLE; i++)
00464 row_spans[i][0] = 2;
00465 (ptr->row1*OVERSAMPLE, ptr->row2*OVERSAMPLE);
00466 for(int i = 0; i < points->total; i++)
00467 {
00468 MaskPoint *point1 = points->values[i];
00469 MaskPoint *point2 = (i >= points->total - 1) ?
00470 points->values[0] :
00471 points->values[i + 1];
00472
00473 float x0 = point1->x;
00474 float y0 = point1->y;
00475 float x1 = point1->x + point1->control_x2;
00476 float y1 = point1->y + point1->control_y2;
00477 float x2 = point2->x + point2->control_x1;
00478 float y2 = point2->y + point2->control_y1;
00479 float x3 = point2->x;
00480 float y3 = point2->y;
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 float cx3, cx2, cx1, cx0, cy3, cy2, cy1, cy0;
00491
00492
00493
00494
00495
00496
00497
00498 cx3 = (- x0 + 3*x1 - 3*x2 + x3) * OVERSAMPLE;
00499 cx2 = ( 3*x0 - 6*x1 + 3*x2) * OVERSAMPLE;
00500 cx1 = (-3*x0 + 3*x1) * OVERSAMPLE;
00501 cx0 = ( x0) * OVERSAMPLE;
00502
00503 cy3 = (- y0 + 3*y1 - 3*y2 + y3) * OVERSAMPLE;
00504 cy2 = ( 3*y0 - 6*y1 + 3*y2) * OVERSAMPLE;
00505 cy1 = (-3*y0 + 3*y1) * OVERSAMPLE;
00506 cy0 = ( y0 - ptr->row1) * OVERSAMPLE;
00507
00508 float maxaccel1 = fabs(2*cy2) + fabs(6*cy3);
00509 float maxaccel2 = fabs(2*cx2) + fabs(6*cx3);
00510
00511 float maxaccel = maxaccel1 > maxaccel2 ? maxaccel1 : maxaccel2;
00512 float h = 1.0;
00513
00514 if(maxaccel > 8.0 * OVERSAMPLE) h = sqrt((8.0 * OVERSAMPLE) / maxaccel);
00515
00516 for(float t = 0.0; t < 1.0; t += h)
00517 {
00518 int x = (int) (cx0 + t*(cx1 + t*(cx2 + t*cx3)));
00519 int y = (int) (cy0 + t*(cy1 + t*(cy2 + t*cy3)));
00520
00521 if (old_x != SHRT_MIN)
00522 draw_line_clamped(old_x, old_y, x, y, oversampled_package_w, oversampled_package_h, ptr->row1 * OVERSAMPLE);
00523 old_x = x;
00524 old_y = y;
00525 }
00526
00527 int x = (int)(x3 * OVERSAMPLE);
00528 int y = (int)((y3 - ptr->row1) * OVERSAMPLE);
00529 draw_line_clamped(old_x, old_y, x, y, oversampled_package_w, oversampled_package_h, ptr->row1 * OVERSAMPLE);
00530 old_x = (int)x;
00531 old_y = (int)y;
00532
00533 }
00534
00535
00536
00537
00538 uint16_t value;
00539 if (mask_color_model == BC_A8)
00540 value = (int)((float)engine->value / 100 * 0xff);
00541 else
00542 value = (int)((float)engine->value / 100 * 0xffff);
00543
00544
00545 for (int i = ptr->row1; i < ptr->row2; i++)
00546 {
00547 short min_x = SHRT_MAX;
00548 short max_x = SHRT_MIN;
00549 int j;
00550 short *span;
00551 short span_p[OVERSAMPLE];
00552 #define P (span_p[j])
00553 #define MAXP (span[0])
00554 int num_empty_spans = 0;
00555
00556 for (j = 0; j < OVERSAMPLE; j++)
00557 {
00558 span = row_spans[j + i * OVERSAMPLE];
00559 P = 2;
00560
00561 if (MAXP != 2) {
00562 if (span[2] < min_x) min_x = span[2];
00563 if (span[MAXP-1] > max_x) max_x = span[MAXP-1];
00564 } else
00565 {
00566 num_empty_spans ++;
00567 }
00568 }
00569 if (num_empty_spans == OVERSAMPLE)
00570 continue;
00571 else
00572 {
00573 if (local_first_nonempty_rowspan < 0 || i < local_first_nonempty_rowspan)
00574 local_first_nonempty_rowspan = i;
00575 if (i > local_last_nonempty_rowspan) local_last_nonempty_rowspan = i;
00576 }
00577
00578
00579 void *output_row = (unsigned char*)mask->get_rows()[i];
00580 min_x = min_x / OVERSAMPLE;
00581 max_x = (max_x + OVERSAMPLE - 1) / OVERSAMPLE;
00582
00583
00584
00585
00586 for (int h = min_x; h <= max_x; h++)
00587 {
00588 short pixelleft = h * OVERSAMPLE;
00589 short pixelright = pixelleft + OVERSAMPLE - 1;
00590 uint32_t coverage = 0;
00591 int num_left = 0;
00592 short right_end = SHRT_MAX;
00593 short right_start = SHRT_MAX;
00594
00595 for (j=0; j< OVERSAMPLE; j++)
00596 {
00597 char chg = 1;
00598 span = row_spans[j + i * OVERSAMPLE];
00599 while (P < MAXP && chg)
00600 {
00601
00602 if (span[P] == span[P+1])
00603 {
00604 P +=2;
00605 continue;
00606 }
00607 if (span[P] <= pixelright)
00608 coverage += MIN(span[P+1], pixelright)
00609 - MAX(span[P], pixelleft) + 1;
00610 if (span[P+1] <= pixelright)
00611 P += 2;
00612 else
00613 chg = 0;
00614 }
00615 if (P == MAXP)
00616 num_left = -OVERSAMPLE;
00617 else
00618 {
00619 if (span[P] <= pixelright)
00620 {
00621 num_left ++;
00622 if (span[P+1] < right_end) right_end = span[P+1];
00623 } else
00624 {
00625 if (span[P] < right_start) right_start = span[P];
00626 }
00627 }
00628 }
00629
00630 coverage *= value;
00631 coverage /= OVERSAMPLE * OVERSAMPLE;
00632
00633
00634 switch (mask_color_model)
00635 {
00636 case BC_A8:
00637 if (((unsigned char *) output_row)[h] < coverage)
00638 ((unsigned char*)output_row)[h] = coverage;
00639 break;
00640 case BC_A16:
00641 if (((uint16_t *) output_row)[h] < coverage)
00642 ((uint16_t *) output_row)[h] = coverage;
00643 break;
00644 case BC_A_FLOAT:
00645 if (((float *) output_row)[h] < coverage/float(0xffff))
00646 ((float *) output_row)[h] = coverage/float(0xffff);
00647 break;
00648 }
00649
00650
00651 if (num_left == OVERSAMPLE)
00652 {
00653
00654
00655 right_end = (right_end / OVERSAMPLE) - 1;
00656 if (right_end > h)
00657 {
00658 if (mask_color_model == BC_A8)
00659 memset((char *)output_row + h + 1, value, right_end - h);
00660 else {
00661
00662 if (mask_color_model == BC_A16) {
00663 for (int z = h +1; z <= right_end; z++)
00664 ((uint16_t *) output_row)[z] = value;
00665 } else {
00666 for (int z = h +1; z <= right_end; z++)
00667 ((float *) output_row)[z] = value/float(0xffff);
00668 }
00669 }
00670 h = right_end;
00671 }
00672 } else
00673 if (num_left == 0)
00674 {
00675
00676
00677 right_start = (right_start / OVERSAMPLE) - 1;
00678 if (right_start > h)
00679 {
00680 h = right_start;
00681 }
00682 }
00683 }
00684 }
00685 }
00686 engine->protect_data.lock();
00687 if (local_first_nonempty_rowspan < engine->first_nonempty_rowspan)
00688 engine->first_nonempty_rowspan = local_first_nonempty_rowspan;
00689 if (local_last_nonempty_rowspan > engine->last_nonempty_rowspan)
00690 engine->last_nonempty_rowspan = local_last_nonempty_rowspan;
00691 engine->protect_data.unlock();
00692
00693
00694
00695
00696 }
00697
00698 SET_TRACE
00699
00700
00701
00702
00703 if(engine->recalculate && engine->feather > 0)
00704 {
00705
00706 pthread_mutex_lock(&engine->stage1_finished_mutex);
00707 engine->stage1_finished_count ++;
00708 if (engine->stage1_finished_count == engine->get_total_packages())
00709 {
00710
00711 pthread_cond_broadcast(&engine->stage1_finished_cond);
00712 }
00713 else
00714 {
00715
00716 while (engine->stage1_finished_count < engine->get_total_packages())
00717 pthread_cond_wait(&engine->stage1_finished_cond, &engine->stage1_finished_mutex);
00718 }
00719 pthread_mutex_unlock(&engine->stage1_finished_mutex);
00720
00721
00722
00723
00724 struct timeval start_time;
00725 gettimeofday(&start_time, 0);
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 int done = 0;
00769 done = do_feather_2(engine->mask,
00770 engine->temp_mask,
00771 engine->feather * 2 - 1,
00772 ptr->row1,
00773 ptr->row2);
00774 if (done) {
00775 engine->realfeather = engine->feather;
00776 }
00777 if (!done)
00778 {
00779
00780 float feather = engine->feather;
00781 engine->realfeather = 0.878441 + 0.988534*feather - 0.0490204 *feather*feather + 0.0012359 *feather*feather*feather;
00782 do_feather(engine->mask,
00783 engine->temp_mask,
00784 engine->realfeather,
00785 ptr->row1,
00786 ptr->row2);
00787 }
00788 int64_t dif= get_difference(&start_time);
00789 printf("diff: %lli\n", dif);
00790 } else
00791 if (engine->feather <= 0) {
00792 engine->realfeather = 0;
00793 }
00794 start_row = MAX (ptr->row1, engine->first_nonempty_rowspan - (int)ceil(engine->realfeather));
00795 end_row = MIN (ptr->row2, engine->last_nonempty_rowspan + 1 + (int)ceil(engine->realfeather));
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 #define APPLY_MASK_SUBTRACT_ALPHA(type, max, components, do_yuv) \
00806 { \
00807 type chroma_offset = (max + 1) / 2; \
00808 for(int i = start_row; i < end_row; i++) \
00809 { \
00810 type *output_row = (type*)engine->output->get_rows()[i]; \
00811 type *mask_row = (type*)engine->mask->get_rows()[i]; \
00812 \
00813 \
00814 for(int j = 0; j < mask_w; j++) \
00815 { \
00816 if(components == 4) \
00817 { \
00818 output_row[3] = output_row[3] * (max - *mask_row) / max; \
00819 } \
00820 else \
00821 { \
00822 output_row[0] = output_row[0] * (max - *mask_row) / max; \
00823 \
00824 output_row[1] = output_row[1] * (max - *mask_row) / max; \
00825 output_row[2] = output_row[2] * (max - *mask_row) / max; \
00826 \
00827 if(do_yuv) \
00828 { \
00829 output_row[1] += chroma_offset * *mask_row / max; \
00830 output_row[2] += chroma_offset * *mask_row / max; \
00831 } \
00832 } \
00833 output_row += components; \
00834 mask_row += 1; \
00835 } \
00836 } \
00837 }
00838
00839 #define APPLY_MASK_MULTIPLY_ALPHA(type, max, components, do_yuv) \
00840 { \
00841 type chroma_offset = (max + 1) / 2; \
00842 for(int i = ptr->row1; i < ptr->row2; i++) \
00843 { \
00844 type *output_row = (type*)engine->output->get_rows()[i]; \
00845 type *mask_row = (type*)engine->mask->get_rows()[i]; \
00846 \
00847 if (components == 4) output_row += 3; \
00848 for(int j = mask_w; j != 0; j--) \
00849 { \
00850 if(components == 4) \
00851 { \
00852 *output_row = *output_row * *mask_row / max; \
00853 } \
00854 else \
00855 { \
00856 output_row[0] = output_row[3] * *mask_row / max; \
00857 \
00858 output_row[1] = output_row[1] * *mask_row / max; \
00859 output_row[2] = output_row[2] * *mask_row / max; \
00860 \
00861 if(do_yuv) \
00862 { \
00863 output_row[1] += chroma_offset * (max - *mask_row) / max; \
00864 output_row[2] += chroma_offset * (max - *mask_row) / max; \
00865 } \
00866 } \
00867 output_row += components; \
00868 mask_row += 1; \
00869 } \
00870 } \
00871 }
00872
00873
00874
00875
00876
00877
00878 int mask_w = engine->mask->get_w();
00879 switch(engine->mode)
00880 {
00881 case MASK_MULTIPLY_ALPHA:
00882 switch(engine->output->get_color_model())
00883 {
00884 case BC_RGB888:
00885 APPLY_MASK_MULTIPLY_ALPHA(unsigned char, 0xff, 3, 0);
00886 break;
00887 case BC_YUV888:
00888 APPLY_MASK_MULTIPLY_ALPHA(unsigned char, 0xff, 3, 1);
00889 break;
00890 case BC_YUVA8888:
00891 case BC_RGBA8888:
00892 APPLY_MASK_MULTIPLY_ALPHA(unsigned char, 0xff, 4, 0);
00893 break;
00894 case BC_RGB161616:
00895 APPLY_MASK_MULTIPLY_ALPHA(uint16_t, 0xffff, 3, 0);
00896 break;
00897 case BC_YUV161616:
00898 APPLY_MASK_MULTIPLY_ALPHA(uint16_t, 0xffff, 3, 1);
00899 break;
00900 case BC_YUVA16161616:
00901 case BC_RGBA16161616:
00902 APPLY_MASK_MULTIPLY_ALPHA(uint16_t, 0xffff, 4, 0);
00903 break;
00904 case BC_RGB_FLOAT:
00905 APPLY_MASK_MULTIPLY_ALPHA(float, 1.0f, 3, 0);
00906 break;
00907 case BC_RGBA_FLOAT:
00908 APPLY_MASK_MULTIPLY_ALPHA(float, 1.0f, 4, 0);
00909 break;
00910 }
00911 break;
00912
00913 case MASK_SUBTRACT_ALPHA:
00914 switch(engine->output->get_color_model())
00915 {
00916 case BC_RGB888:
00917 APPLY_MASK_SUBTRACT_ALPHA(unsigned char, 0xff, 3, 0);
00918 break;
00919 case BC_YUV888:
00920 APPLY_MASK_SUBTRACT_ALPHA(unsigned char, 0xff, 3, 1);
00921 break;
00922 case BC_YUVA8888:
00923 case BC_RGBA8888:
00924 APPLY_MASK_SUBTRACT_ALPHA(unsigned char, 0xff, 4, 0);
00925 break;
00926 case BC_RGB161616:
00927 APPLY_MASK_SUBTRACT_ALPHA(uint16_t, 0xffff, 3, 0);
00928 break;
00929 case BC_YUV161616:
00930 APPLY_MASK_SUBTRACT_ALPHA(uint16_t, 0xffff, 3, 1);
00931 break;
00932 case BC_YUVA16161616:
00933 case BC_RGBA16161616:
00934 APPLY_MASK_SUBTRACT_ALPHA(uint16_t, 0xffff, 4, 0);
00935 break;
00936 case BC_RGB_FLOAT:
00937 APPLY_MASK_SUBTRACT_ALPHA(float, 1.0f, 3, 0);
00938 break;
00939 case BC_RGBA_FLOAT:
00940 APPLY_MASK_SUBTRACT_ALPHA(float, 1.0f, 4, 0);
00941 break;
00942 }
00943 break;
00944 }
00945
00946
00947
00948
00949 }
00950
00951
00952
00953
00954
00955 MaskEngine::MaskEngine(int cpus)
00956 : LoadServer(cpus, cpus )
00957
00958 {
00959 mask = 0;
00960 pthread_mutex_init(&stage1_finished_mutex, NULL);
00961 pthread_cond_init(&stage1_finished_cond, NULL);
00962 }
00963
00964 MaskEngine::~MaskEngine()
00965 {
00966 pthread_cond_destroy(&stage1_finished_cond);
00967 pthread_mutex_destroy(&stage1_finished_mutex);
00968 if(mask)
00969 {
00970 delete mask;
00971 delete temp_mask;
00972 }
00973
00974 for(int i = 0; i < point_sets.total; i++)
00975 {
00976 ArrayList<MaskPoint*> *points = point_sets.values[i];
00977 points->remove_all_objects();
00978 }
00979 point_sets.remove_all_objects();
00980 }
00981
00982 int MaskEngine::points_equivalent(ArrayList<MaskPoint*> *new_points,
00983 ArrayList<MaskPoint*> *points)
00984 {
00985
00986 if(new_points->total != points->total) return 0;
00987
00988 for(int i = 0; i < new_points->total; i++)
00989 {
00990 if(!(*new_points->values[i] == *points->values[i])) return 0;
00991 }
00992
00993 return 1;
00994 }
00995
00996 void MaskEngine::do_mask(VFrame *output,
00997 int64_t start_position,
00998 double frame_rate,
00999 double project_frame_rate,
01000 MaskAutos *keyframe_set,
01001 int direction,
01002 int before_plugins)
01003 {
01004 int64_t start_position_project = (int64_t)(start_position *
01005 project_frame_rate /
01006 frame_rate);
01007 Auto *current = 0;
01008 MaskAuto *default_auto = (MaskAuto*)keyframe_set->default_auto;
01009 MaskAuto *keyframe = (MaskAuto*)keyframe_set->get_prev_auto(start_position_project,
01010 direction,
01011 current);
01012
01013 if (keyframe->apply_before_plugins != before_plugins)
01014 return;
01015
01016
01017 int total_points = 0;
01018 for(int i = 0; i < keyframe->masks.total; i++)
01019 {
01020 SubMask *mask = keyframe->get_submask(i);
01021 int submask_points = mask->points.total;
01022 if(submask_points > 1) total_points += submask_points;
01023 }
01024
01025
01026
01027 if(total_points < 2 ||
01028 (keyframe->value == 0 && default_auto->mode == MASK_SUBTRACT_ALPHA))
01029 {
01030 return;
01031 }
01032
01033
01034 if(keyframe->value == 0 && default_auto->mode == MASK_MULTIPLY_ALPHA)
01035 {
01036 output->clear_frame();
01037 return;
01038 }
01039
01040
01041
01042 int new_color_model = 0;
01043 recalculate = 0;
01044
01045 switch(output->get_color_model())
01046 {
01047 case BC_RGB_FLOAT:
01048 case BC_RGBA_FLOAT:
01049 new_color_model = BC_A_FLOAT;
01050 break;
01051
01052 case BC_RGB888:
01053 case BC_RGBA8888:
01054 case BC_YUV888:
01055 case BC_YUVA8888:
01056 new_color_model = BC_A8;
01057 break;
01058
01059 case BC_RGB161616:
01060 case BC_RGBA16161616:
01061 case BC_YUV161616:
01062 case BC_YUVA16161616:
01063 new_color_model = BC_A16;
01064 break;
01065 }
01066
01067
01068 SET_TRACE
01069
01070 if(mask &&
01071 (mask->get_w() != output->get_w() ||
01072 mask->get_h() != output->get_h() ||
01073 mask->get_color_model() != new_color_model))
01074 {
01075 delete mask;
01076 delete temp_mask;
01077 mask = 0;
01078 recalculate = 1;
01079 }
01080
01081 if(!recalculate)
01082 {
01083 if(point_sets.total != keyframe_set->total_submasks(start_position_project,
01084 direction))
01085 recalculate = 1;
01086 }
01087
01088 if(!recalculate)
01089 {
01090 for(int i = 0;
01091 i < keyframe_set->total_submasks(start_position_project,
01092 direction) && !recalculate;
01093 i++)
01094 {
01095 ArrayList<MaskPoint*> *new_points = new ArrayList<MaskPoint*>;
01096 keyframe_set->get_points(new_points,
01097 i,
01098 start_position_project,
01099 direction);
01100 if(!points_equivalent(new_points, point_sets.values[i])) recalculate = 1;
01101 new_points->remove_all_objects();
01102 delete new_points;
01103 }
01104 }
01105
01106 if(recalculate ||
01107 !EQUIV(keyframe->feather, feather) ||
01108 !EQUIV(keyframe->value, value))
01109 {
01110 recalculate = 1;
01111 if(!mask)
01112 {
01113 mask = new VFrame(0,
01114 output->get_w(),
01115 output->get_h(),
01116 new_color_model);
01117 temp_mask = new VFrame(0,
01118 output->get_w(),
01119 output->get_h(),
01120 new_color_model);
01121 }
01122 if(keyframe->feather > 0)
01123 temp_mask->clear_frame();
01124 else
01125 mask->clear_frame();
01126
01127 for(int i = 0; i < point_sets.total; i++)
01128 {
01129 ArrayList<MaskPoint*> *points = point_sets.values[i];
01130 points->remove_all_objects();
01131 }
01132 point_sets.remove_all_objects();
01133
01134 for(int i = 0;
01135 i < keyframe_set->total_submasks(start_position_project,
01136 direction);
01137 i++)
01138 {
01139 ArrayList<MaskPoint*> *new_points = new ArrayList<MaskPoint*>;
01140 keyframe_set->get_points(new_points,
01141 i,
01142 start_position_project,
01143 direction);
01144 point_sets.append(new_points);
01145 }
01146 }
01147
01148
01149
01150 this->output = output;
01151 this->mode = default_auto->mode;
01152 this->feather = keyframe->feather;
01153 this->value = keyframe->value;
01154
01155
01156
01157 SET_TRACE
01158 process_packages();
01159 SET_TRACE
01160
01161
01162 }
01163
01164 void MaskEngine::init_packages()
01165 {
01166 SET_TRACE
01167
01168 int division = (int)((float)output->get_h() / (get_total_packages()) + 0.5);
01169 if(division < 1) division = 1;
01170
01171 stage1_finished_count = 0;
01172 if (recalculate) {
01173 last_nonempty_rowspan = SHRT_MIN;
01174 first_nonempty_rowspan = SHRT_MAX;
01175 }
01176 SET_TRACE
01177
01178 for(int i = 0; i < get_total_packages(); i++)
01179 {
01180 MaskPackage *pkg = (MaskPackage*)get_package(i);
01181 pkg->row1 = division * i;
01182 pkg->row2 = MIN (division * i + division, output->get_h());
01183
01184 if(i == get_total_packages() - 1)
01185 {
01186 pkg->row2 = pkg->row2 = output->get_h();
01187 }
01188
01189 }
01190 SET_TRACE
01191
01192 }
01193
01194 LoadClient* MaskEngine::new_client()
01195 {
01196 return new MaskUnit(this);
01197 }
01198
01199 LoadPackage* MaskEngine::new_package()
01200 {
01201 return new MaskPackage;
01202 }
01203