00001 #include "clip.h"
00002 #include "colormodels.h"
00003 #include "filexml.h"
00004 #include "picon_png.h"
00005 #include "aging.h"
00006 #include "agingwindow.h"
00007 #include "effecttv.h"
00008
00009 #include <stdint.h>
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <unistd.h>
00013
00014 #include <libintl.h>
00015 #define _(String) gettext(String)
00016 #define gettext_noop(String) String
00017 #define N_(String) gettext_noop (String)
00018
00019
00020
00021
00022
00023 REGISTER_PLUGIN(AgingMain)
00024
00025
00026
00027
00028
00029
00030 int AgingConfig::dx[] = { 1, 1, 0, -1, -1, -1, 0, 1};
00031 int AgingConfig::dy[] = { 0, -1, -1, -1, 0, 1, 1, 1};
00032
00033 AgingConfig::AgingConfig()
00034 {
00035 dust_interval = 0;
00036 pits_interval = 0;
00037 aging_mode = 0;
00038 area_scale = 10;
00039 scratch_lines = 7;
00040 colorage = 1;
00041 scratch = 1;
00042 pits = 1;
00043 dust = 1;
00044 }
00045
00046 AgingMain::AgingMain(PluginServer *server)
00047 : PluginVClient(server)
00048 {
00049 PLUGIN_CONSTRUCTOR_MACRO
00050 aging_server = 0;
00051 }
00052
00053 AgingMain::~AgingMain()
00054 {
00055 PLUGIN_DESTRUCTOR_MACRO
00056 if(aging_server) delete aging_server;
00057 }
00058
00059 char* AgingMain::plugin_title() { return N_("AgingTV"); }
00060 int AgingMain::is_realtime() { return 1; }
00061
00062 NEW_PICON_MACRO(AgingMain)
00063
00064 SHOW_GUI_MACRO(AgingMain, AgingThread)
00065
00066 SET_STRING_MACRO(AgingMain)
00067
00068 RAISE_WINDOW_MACRO(AgingMain)
00069
00070 int AgingMain::load_defaults()
00071 {
00072 return 0;
00073 }
00074
00075 int AgingMain::save_defaults()
00076 {
00077 return 0;
00078 }
00079
00080 void AgingMain::load_configuration()
00081 {
00082 }
00083
00084
00085 void AgingMain::save_data(KeyFrame *keyframe)
00086 {
00087 }
00088
00089 void AgingMain::read_data(KeyFrame *keyframe)
00090 {
00091 }
00092
00093
00094 int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00095 {
00096
00097 load_configuration();
00098
00099 this->input_ptr = input_ptr;
00100 this->output_ptr = output_ptr;
00101
00102 if(!aging_server) aging_server = new AgingServer(this,
00103 PluginClient::smp + 1,
00104 PluginClient::smp + 1);
00105 aging_server->process_packages();
00106
00107
00108 return 0;
00109 }
00110
00111
00112
00113 AgingServer::AgingServer(AgingMain *plugin, int total_clients, int total_packages)
00114 : LoadServer(1, 1 )
00115 {
00116 this->plugin = plugin;
00117 }
00118
00119
00120 LoadClient* AgingServer::new_client()
00121 {
00122 return new AgingClient(this);
00123 }
00124
00125
00126
00127
00128 LoadPackage* AgingServer::new_package()
00129 {
00130 return new AgingPackage;
00131 }
00132
00133
00134
00135 void AgingServer::init_packages()
00136 {
00137 for(int i = 0; i < get_total_packages(); i++)
00138 {
00139 AgingPackage *package = (AgingPackage*)get_package(i);
00140 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
00141 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
00142 }
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152 AgingClient::AgingClient(AgingServer *server)
00153 : LoadClient(server)
00154 {
00155 this->plugin = server->plugin;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 #define COLORAGE(type, components) \
00167 { \
00168 int a, b; \
00169 int i, j, k; \
00170 \
00171 for(i = 0; i < h; i++) \
00172 { \
00173 for(j = 0; j < w; j++) \
00174 { \
00175 for(k = 0; k < 3; k++) \
00176 { \
00177 if(sizeof(type) == 4) \
00178 { \
00179 a = (int)(((type**)input_rows)[i][j * components + k] * 0xffff); \
00180 CLAMP(a, 0, 0xffff); \
00181 } \
00182 else \
00183 a = (int)((type**)input_rows)[i][j * components + k]; \
00184 \
00185 if(sizeof(type) == 4) \
00186 { \
00187 b = (a & 0xffff) >> 2; \
00188 ((type**)output_rows)[i][j * components + k] = \
00189 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)) / 0xffff; \
00190 } \
00191 else \
00192 if(sizeof(type) == 2) \
00193 { \
00194 b = (a & 0xffff) >> 2; \
00195 ((type**)output_rows)[i][j * components + k] = \
00196 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)); \
00197 } \
00198 else \
00199 { \
00200 b = (a & 0xff) >> 2; \
00201 ((type**)output_rows)[i][j * components + k] = \
00202 (type)(a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10)); \
00203 } \
00204 } \
00205 } \
00206 } \
00207 }
00208
00209 void AgingClient::coloraging(unsigned char **output_rows,
00210 unsigned char **input_rows,
00211 int color_model,
00212 int w,
00213 int h)
00214 {
00215 switch(color_model)
00216 {
00217 case BC_RGB888:
00218 case BC_YUV888:
00219 COLORAGE(uint8_t, 3);
00220 break;
00221
00222 case BC_RGB_FLOAT:
00223 COLORAGE(float, 3);
00224 break;
00225
00226 case BC_RGBA_FLOAT:
00227 COLORAGE(float, 4);
00228 break;
00229
00230 case BC_RGBA8888:
00231 case BC_YUVA8888:
00232 COLORAGE(uint8_t, 4);
00233 break;
00234
00235 case BC_RGB161616:
00236 case BC_YUV161616:
00237 COLORAGE(uint16_t, 3);
00238 break;
00239
00240 case BC_RGBA16161616:
00241 case BC_YUVA16161616:
00242 COLORAGE(uint16_t, 4);
00243 break;
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252 #define SCRATCHES(type, components, chroma) \
00253 { \
00254 int i, j, y, y1, y2; \
00255 type *p; \
00256 int a, b; \
00257 int w_256 = w * 256; \
00258 \
00259 for(i = 0; i < plugin->config.scratch_lines; i++) \
00260 { \
00261 if(plugin->config.scratches[i].life) \
00262 { \
00263 plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
00264 if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256) \
00265 { \
00266 plugin->config.scratches[i].life = 0; \
00267 break; \
00268 } \
00269 \
00270 p = (type*)output_rows[0] + \
00271 (plugin->config.scratches[i].x >> 8) * \
00272 components; \
00273 \
00274 if(plugin->config.scratches[i].init) \
00275 { \
00276 y1 = plugin->config.scratches[i].init; \
00277 plugin->config.scratches[i].init = 0; \
00278 } \
00279 else \
00280 { \
00281 y1 = 0; \
00282 } \
00283 \
00284 plugin->config.scratches[i].life--; \
00285 if(plugin->config.scratches[i].life) \
00286 { \
00287 y2 = h; \
00288 } \
00289 else \
00290 { \
00291 y2 = EffectTV::fastrand() % h; \
00292 } \
00293 \
00294 for(y = y1; y < y2; y++) \
00295 { \
00296 for(j = 0; j < (chroma ? 1 : 3); j++) \
00297 { \
00298 if(sizeof(type) == 4) \
00299 { \
00300 int temp = (int)(p[j] * 0xffff); \
00301 CLAMP(temp, 0, 0xffff); \
00302 a = temp & 0xfeff; \
00303 a += 0x2000; \
00304 b = a & 0x10000; \
00305 p[j] = (type)(a | (b - (b >> 8))) / 0xffff; \
00306 } \
00307 else \
00308 if(sizeof(type) == 2) \
00309 { \
00310 int temp = (int)p[j]; \
00311 a = temp & 0xfeff; \
00312 a += 0x2000; \
00313 b = a & 0x10000; \
00314 p[j] = (type)(a | (b - (b >> 8))); \
00315 } \
00316 else \
00317 { \
00318 int temp = (int)p[j]; \
00319 a = temp & 0xfe; \
00320 a += 0x20; \
00321 b = a & 0x100; \
00322 p[j] = (type)(a | (b - (b >> 8))); \
00323 } \
00324 } \
00325 \
00326 if(chroma) \
00327 { \
00328 p[1] = chroma; \
00329 p[2] = chroma; \
00330 } \
00331 p += w * components; \
00332 } \
00333 } \
00334 else \
00335 { \
00336 if((EffectTV::fastrand() & 0xf0000000) == 0) \
00337 { \
00338 plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
00339 plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
00340 plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
00341 plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
00342 } \
00343 } \
00344 } \
00345 }
00346
00347
00348
00349 void AgingClient::scratching(unsigned char **output_rows,
00350 int color_model,
00351 int w,
00352 int h)
00353 {
00354 switch(color_model)
00355 {
00356 case BC_RGB888:
00357 SCRATCHES(uint8_t, 3, 0);
00358 break;
00359
00360 case BC_RGB_FLOAT:
00361 SCRATCHES(float, 3, 0);
00362 break;
00363
00364 case BC_YUV888:
00365 SCRATCHES(uint8_t, 3, 0x80);
00366 break;
00367
00368 case BC_RGBA_FLOAT:
00369 SCRATCHES(float, 4, 0);
00370 break;
00371
00372 case BC_RGBA8888:
00373 SCRATCHES(uint8_t, 4, 0);
00374 break;
00375
00376 case BC_YUVA8888:
00377 SCRATCHES(uint8_t, 4, 0x80);
00378 break;
00379
00380 case BC_RGB161616:
00381 SCRATCHES(uint16_t, 3, 0);
00382 break;
00383
00384 case BC_YUV161616:
00385 SCRATCHES(uint16_t, 3, 0x8000);
00386 break;
00387
00388 case BC_RGBA16161616:
00389 SCRATCHES(uint16_t, 4, 0);
00390 break;
00391
00392 case BC_YUVA16161616:
00393 SCRATCHES(uint16_t, 4, 0x8000);
00394 break;
00395 }
00396 }
00397
00398
00399
00400 #define PITS(type, components, luma, chroma) \
00401 { \
00402 int i, j, k; \
00403 int pnum, size, pnumscale; \
00404 int x, y; \
00405 \
00406 pnumscale = plugin->config.area_scale * 2; \
00407 \
00408 if(plugin->config.pits_interval) \
00409 { \
00410 pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
00411 plugin->config.pits_interval--; \
00412 } \
00413 else \
00414 { \
00415 pnum = EffectTV::fastrand() % pnumscale; \
00416 if((EffectTV::fastrand() & 0xf8000000) == 0) \
00417 { \
00418 plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
00419 } \
00420 } \
00421 \
00422 for(i = 0; i < pnum; i++) \
00423 { \
00424 x = EffectTV::fastrand() % (w - 1); \
00425 y = EffectTV::fastrand() % (h - 1); \
00426 \
00427 size = EffectTV::fastrand() >> 28; \
00428 \
00429 for(j = 0; j < size; j++) \
00430 { \
00431 x = x + EffectTV::fastrand() % 3 - 1; \
00432 y = y + EffectTV::fastrand() % 3 - 1; \
00433 \
00434 CLAMP(x, 0, w - 1); \
00435 CLAMP(y, 0, h - 1); \
00436 for(k = 0; k < (chroma ? 1 : 3); k++) \
00437 { \
00438 ((type**)output_rows)[y][x * components + k] = luma; \
00439 } \
00440 \
00441 if(chroma) \
00442 { \
00443 ((type**)output_rows)[y][x * components + 1] = chroma; \
00444 ((type**)output_rows)[y][x * components + 2] = chroma; \
00445 } \
00446 \
00447 } \
00448 } \
00449 }
00450
00451
00452
00453
00454
00455
00456 void AgingClient::pits(unsigned char **output_rows,
00457 int color_model,
00458 int w,
00459 int h)
00460 {
00461 switch(color_model)
00462 {
00463 case BC_RGB888:
00464 PITS(uint8_t, 3, 0xc0, 0);
00465 break;
00466 case BC_RGB_FLOAT:
00467 PITS(float, 3, (float)0xc0 / 0xff, 0);
00468 break;
00469 case BC_YUV888:
00470 PITS(uint8_t, 3, 0xc0, 0x80);
00471 break;
00472
00473 case BC_RGBA_FLOAT:
00474 PITS(float, 4, (float)0xc0 / 0xff, 0);
00475 break;
00476 case BC_RGBA8888:
00477 PITS(uint8_t, 4, 0xc0, 0);
00478 break;
00479 case BC_YUVA8888:
00480 PITS(uint8_t, 4, 0xc0, 0x80);
00481 break;
00482
00483 case BC_RGB161616:
00484 PITS(uint16_t, 3, 0xc000, 0);
00485 break;
00486 case BC_YUV161616:
00487 PITS(uint16_t, 3, 0xc000, 0x8000);
00488 break;
00489
00490 case BC_RGBA16161616:
00491 PITS(uint16_t, 4, 0xc000, 0);
00492 break;
00493 case BC_YUVA16161616:
00494 PITS(uint16_t, 4, 0xc000, 0x8000);
00495 break;
00496 }
00497 }
00498
00499
00500 #define DUSTS(type, components, luma, chroma) \
00501 { \
00502 int i, j, k; \
00503 int dnum; \
00504 int d, len; \
00505 int x, y; \
00506 \
00507 if(plugin->config.dust_interval == 0) \
00508 { \
00509 if((EffectTV::fastrand() & 0xf0000000) == 0) \
00510 { \
00511 plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
00512 } \
00513 return; \
00514 } \
00515 \
00516 dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
00517 \
00518 for(i = 0; i < dnum; i++) \
00519 { \
00520 x = EffectTV::fastrand() % w; \
00521 y = EffectTV::fastrand() % h; \
00522 d = EffectTV::fastrand() >> 29; \
00523 len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
00524 \
00525 for(j = 0; j < len; j++) \
00526 { \
00527 CLAMP(x, 0, w - 1); \
00528 CLAMP(y, 0, h - 1); \
00529 for(k = 0; k < (chroma ? 1 : 3); k++) \
00530 { \
00531 ((type**)output_rows)[y][x * components + k] = luma; \
00532 } \
00533 \
00534 if(chroma) \
00535 { \
00536 ((type**)output_rows)[y][x * components + 1] = chroma; \
00537 ((type**)output_rows)[y][x * components + 2] = chroma; \
00538 } \
00539 \
00540 y += AgingConfig::dy[d]; \
00541 x += AgingConfig::dx[d]; \
00542 \
00543 if(x < 0 || x >= w) break; \
00544 if(y < 0 || y >= h) break; \
00545 \
00546 \
00547 d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
00548 } \
00549 } \
00550 plugin->config.dust_interval--; \
00551 }
00552
00553
00554
00555
00556 void AgingClient::dusts(unsigned char **output_rows,
00557 int color_model,
00558 int w,
00559 int h)
00560 {
00561 switch(color_model)
00562 {
00563 case BC_RGB888:
00564 DUSTS(uint8_t, 3, 0x10, 0);
00565 break;
00566
00567 case BC_RGB_FLOAT:
00568 DUSTS(float, 3, (float)0x10 / 0xff, 0);
00569 break;
00570
00571 case BC_YUV888:
00572 DUSTS(uint8_t, 3, 0x10, 0x80);
00573 break;
00574
00575 case BC_RGBA_FLOAT:
00576 DUSTS(float, 4, (float)0x10 / 0xff, 0);
00577 break;
00578
00579 case BC_RGBA8888:
00580 DUSTS(uint8_t, 4, 0x10, 0);
00581 break;
00582
00583 case BC_YUVA8888:
00584 DUSTS(uint8_t, 4, 0x10, 0x80);
00585 break;
00586
00587 case BC_RGB161616:
00588 DUSTS(uint16_t, 3, 0x1000, 0);
00589 break;
00590
00591 case BC_YUV161616:
00592 DUSTS(uint16_t, 3, 0x1000, 0x8000);
00593 break;
00594
00595 case BC_RGBA16161616:
00596 DUSTS(uint16_t, 4, 0x1000, 0);
00597 break;
00598
00599 case BC_YUVA16161616:
00600 DUSTS(uint16_t, 4, 0x1000, 0x8000);
00601 break;
00602 }
00603 }
00604
00605
00606
00607 void AgingClient::process_package(LoadPackage *package)
00608 {
00609
00610 AgingPackage *local_package = (AgingPackage*)package;
00611 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
00612 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
00613
00614
00615 if(plugin->config.colorage)
00616 coloraging(output_rows,
00617 input_rows,
00618 plugin->input_ptr->get_color_model(),
00619 plugin->input_ptr->get_w(),
00620 local_package->row2 - local_package->row1);
00621
00622 if(plugin->config.scratch)
00623 scratching(output_rows,
00624 plugin->input_ptr->get_color_model(),
00625 plugin->input_ptr->get_w(),
00626 local_package->row2 - local_package->row1);
00627
00628 if(plugin->config.pits)
00629 pits(output_rows,
00630 plugin->input_ptr->get_color_model(),
00631 plugin->input_ptr->get_w(),
00632 local_package->row2 - local_package->row1);
00633
00634 if(plugin->config.dust)
00635 dusts(output_rows,
00636 plugin->input_ptr->get_color_model(),
00637 plugin->input_ptr->get_w(),
00638 local_package->row2 - local_package->row1);
00639
00640 }
00641
00642
00643
00644 AgingPackage::AgingPackage()
00645 {
00646 }
00647
00648
00649