4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bccmodels.h"
26 #include "agingwindow.h"
40 REGISTER_PLUGIN(AgingMain)
47 int AgingConfig::dx[] = { 1, 1, 0, -1, -1, -1, 0, 1};
48 int AgingConfig::dy[] = { 0, -1, -1, -1, 0, 1, 1, 1};
50 AgingConfig::AgingConfig()
63 AgingMain::AgingMain(PluginServer *server)
64 : PluginVClient(server)
70 AgingMain::~AgingMain()
73 if(aging_server) delete aging_server;
76 const char* AgingMain::plugin_title() { return _("AgingTV"); }
77 int AgingMain::is_realtime() { return 1; }
79 NEW_WINDOW_MACRO(AgingMain, AgingWindow)
81 int AgingMain::load_defaults()
86 int AgingMain::save_defaults()
91 int AgingMain::load_configuration()
97 void AgingMain::save_data(KeyFrame *keyframe)
101 void AgingMain::read_data(KeyFrame *keyframe)
106 int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
108 //printf("AgingMain::process_realtime 1\n");
109 load_configuration();
110 //printf("AgingMain::process_realtime 1\n");
111 this->input_ptr = input_ptr;
112 this->output_ptr = output_ptr;
114 if(!aging_server) aging_server = new AgingServer(this,
115 PluginClient::smp + 1,
116 PluginClient::smp + 1);
117 aging_server->process_packages();
118 //printf("AgingMain::process_realtime 2\n");
125 AgingServer::AgingServer(AgingMain *plugin, int total_clients, int total_packages)
126 : LoadServer(1, 1 /* total_clients, total_packages */)
128 this->plugin = plugin;
132 LoadClient* AgingServer::new_client()
134 return new AgingClient(this);
140 LoadPackage* AgingServer::new_package()
142 return new AgingPackage;
147 void AgingServer::init_packages()
149 for(int i = 0; i < get_total_packages(); i++)
151 AgingPackage *package = (AgingPackage*)get_package(i);
152 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
153 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
164 AgingClient::AgingClient(AgingServer *server)
167 this->plugin = server->plugin;
178 #define COLORAGE(type, components) \
183 for(i = 0; i < h; i++) \
185 for(j = 0; j < w; j++) \
187 for(k = 0; k < 3; k++) \
189 if(sizeof(type) == 4) \
191 a = (int)(((type**)input_rows)[i][j * components + k] * 0xffff); \
192 CLAMP(a, 0, 0xffff); \
195 a = (int)((type**)input_rows)[i][j * components + k]; \
197 if(sizeof(type) == 4) \
199 b = (a & 0xffff) >> 2; \
200 ((type**)output_rows)[i][j * components + k] = \
201 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)) / 0xffff; \
204 if(sizeof(type) == 2) \
206 b = (a & 0xffff) >> 2; \
207 ((type**)output_rows)[i][j * components + k] = \
208 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)); \
212 b = (a & 0xff) >> 2; \
213 ((type**)output_rows)[i][j * components + k] = \
214 (type)(a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10)); \
221 void AgingClient::coloraging(unsigned char **output_rows,
222 unsigned char **input_rows,
231 COLORAGE(uint8_t, 3);
244 COLORAGE(uint8_t, 4);
249 COLORAGE(uint16_t, 3);
252 case BC_RGBA16161616:
253 case BC_YUVA16161616:
254 COLORAGE(uint16_t, 4);
264 #define SCRATCHES(type, components, chroma) \
266 int i, j, y, y1, y2; \
269 int w_256 = w * 256; \
271 for(i = 0; i < plugin->config.scratch_lines; i++) \
273 if(plugin->config.scratches[i].life) \
275 plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
276 if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256) \
278 plugin->config.scratches[i].life = 0; \
282 p = (type*)output_rows[0] + \
283 (plugin->config.scratches[i].x >> 8) * \
286 if(plugin->config.scratches[i].init) \
288 y1 = plugin->config.scratches[i].init; \
289 plugin->config.scratches[i].init = 0; \
296 plugin->config.scratches[i].life--; \
297 if(plugin->config.scratches[i].life) \
303 y2 = EffectTV::fastrand() % h; \
306 for(y = y1; y < y2; y++) \
308 for(j = 0; j < (chroma ? 1 : 3); j++) \
310 if(sizeof(type) == 4) \
312 int temp = (int)(p[j] * 0xffff); \
313 CLAMP(temp, 0, 0xffff); \
317 p[j] = (type)(a | (b - (b >> 8))) / 0xffff; \
320 if(sizeof(type) == 2) \
322 int temp = (int)p[j]; \
326 p[j] = (type)(a | (b - (b >> 8))); \
330 int temp = (int)p[j]; \
334 p[j] = (type)(a | (b - (b >> 8))); \
343 p += w * components; \
348 if((EffectTV::fastrand() & 0xf0000000) == 0) \
350 plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
351 plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
352 plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
353 plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
361 void AgingClient::scratching(unsigned char **output_rows,
369 SCRATCHES(uint8_t, 3, 0);
373 SCRATCHES(float, 3, 0);
377 SCRATCHES(uint8_t, 3, 0x80);
381 SCRATCHES(float, 4, 0);
385 SCRATCHES(uint8_t, 4, 0);
389 SCRATCHES(uint8_t, 4, 0x80);
393 SCRATCHES(uint16_t, 3, 0);
397 SCRATCHES(uint16_t, 3, 0x8000);
400 case BC_RGBA16161616:
401 SCRATCHES(uint16_t, 4, 0);
404 case BC_YUVA16161616:
405 SCRATCHES(uint16_t, 4, 0x8000);
412 #define PITS(type, components, luma, chroma) \
415 int pnum, size, pnumscale; \
418 pnumscale = plugin->config.area_scale * 2; \
420 if(plugin->config.pits_interval) \
422 pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
423 plugin->config.pits_interval--; \
427 pnum = EffectTV::fastrand() % pnumscale; \
428 if((EffectTV::fastrand() & 0xf8000000) == 0) \
430 plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
434 for(i = 0; i < pnum; i++) \
436 x = EffectTV::fastrand() % (w - 1); \
437 y = EffectTV::fastrand() % (h - 1); \
439 size = EffectTV::fastrand() >> 28; \
441 for(j = 0; j < size; j++) \
443 x = x + EffectTV::fastrand() % 3 - 1; \
444 y = y + EffectTV::fastrand() % 3 - 1; \
446 CLAMP(x, 0, w - 1); \
447 CLAMP(y, 0, h - 1); \
448 for(k = 0; k < (chroma ? 1 : 3); k++) \
450 ((type**)output_rows)[y][x * components + k] = luma; \
455 ((type**)output_rows)[y][x * components + 1] = chroma; \
456 ((type**)output_rows)[y][x * components + 2] = chroma; \
468 void AgingClient::pits(unsigned char **output_rows,
476 PITS(uint8_t, 3, 0xc0, 0);
479 PITS(float, 3, (float)0xc0 / 0xff, 0);
482 PITS(uint8_t, 3, 0xc0, 0x80);
486 PITS(float, 4, (float)0xc0 / 0xff, 0);
489 PITS(uint8_t, 4, 0xc0, 0);
492 PITS(uint8_t, 4, 0xc0, 0x80);
496 PITS(uint16_t, 3, 0xc000, 0);
499 PITS(uint16_t, 3, 0xc000, 0x8000);
502 case BC_RGBA16161616:
503 PITS(uint16_t, 4, 0xc000, 0);
505 case BC_YUVA16161616:
506 PITS(uint16_t, 4, 0xc000, 0x8000);
512 #define DUSTS(type, components, luma, chroma) \
519 if(plugin->config.dust_interval == 0) \
521 if((EffectTV::fastrand() & 0xf0000000) == 0) \
523 plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
528 dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
530 for(i = 0; i < dnum; i++) \
532 x = EffectTV::fastrand() % w; \
533 y = EffectTV::fastrand() % h; \
534 d = EffectTV::fastrand() >> 29; \
535 len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
537 for(j = 0; j < len; j++) \
539 CLAMP(x, 0, w - 1); \
540 CLAMP(y, 0, h - 1); \
541 for(k = 0; k < (chroma ? 1 : 3); k++) \
543 ((type**)output_rows)[y][x * components + k] = luma; \
548 ((type**)output_rows)[y][x * components + 1] = chroma; \
549 ((type**)output_rows)[y][x * components + 2] = chroma; \
552 y += AgingConfig::dy[d]; \
553 x += AgingConfig::dx[d]; \
555 if(x < 0 || x >= w) break; \
556 if(y < 0 || y >= h) break; \
559 d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
562 plugin->config.dust_interval--; \
568 void AgingClient::dusts(unsigned char **output_rows,
576 DUSTS(uint8_t, 3, 0x10, 0);
580 DUSTS(float, 3, (float)0x10 / 0xff, 0);
584 DUSTS(uint8_t, 3, 0x10, 0x80);
588 DUSTS(float, 4, (float)0x10 / 0xff, 0);
592 DUSTS(uint8_t, 4, 0x10, 0);
596 DUSTS(uint8_t, 4, 0x10, 0x80);
600 DUSTS(uint16_t, 3, 0x1000, 0);
604 DUSTS(uint16_t, 3, 0x1000, 0x8000);
607 case BC_RGBA16161616:
608 DUSTS(uint16_t, 4, 0x1000, 0);
611 case BC_YUVA16161616:
612 DUSTS(uint16_t, 4, 0x1000, 0x8000);
619 void AgingClient::process_package(LoadPackage *package)
621 //printf("AgingClient::process_package 1\n");
622 AgingPackage *local_package = (AgingPackage*)package;
623 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
624 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
626 //printf("AgingClient::process_package 1\n");
627 if(plugin->config.colorage)
628 coloraging(output_rows,
630 plugin->input_ptr->get_color_model(),
631 plugin->input_ptr->get_w(),
632 local_package->row2 - local_package->row1);
633 //printf("AgingClient::process_package 2\n");
634 if(plugin->config.scratch)
635 scratching(output_rows,
636 plugin->input_ptr->get_color_model(),
637 plugin->input_ptr->get_w(),
638 local_package->row2 - local_package->row1);
639 //printf("AgingClient::process_package 3\n");
640 if(plugin->config.pits)
642 plugin->input_ptr->get_color_model(),
643 plugin->input_ptr->get_w(),
644 local_package->row2 - local_package->row1);
645 //printf("AgingClient::process_package 4 %d\n", plugin->config.dust);
646 if(plugin->config.dust)
648 plugin->input_ptr->get_color_model(),
649 plugin->input_ptr->get_w(),
650 local_package->row2 - local_package->row1);
651 //printf("AgingClient::process_package 5\n");
656 AgingPackage::AgingPackage()