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