00001 #include "clip.h"
00002 #include "colormodels.h"
00003 #include "effecttv.h"
00004 #include "filexml.h"
00005 #include "language.h"
00006 #include "picon_png.h"
00007 #include "plugincolors.h"
00008 #include "burn.h"
00009 #include "burnwindow.h"
00010
00011 #include <stdint.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014
00015
00016
00017 REGISTER_PLUGIN(BurnMain)
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 BurnConfig::BurnConfig()
00031 {
00032 threshold = 50;
00033 decay = 15;
00034 recycle = 1.0;
00035 }
00036
00037 BurnMain::BurnMain(PluginServer *server)
00038 : PluginVClient(server)
00039 {
00040 input_ptr = 0;
00041 output_ptr = 0;
00042 burn_server = 0;
00043 buffer = 0;
00044 effecttv = 0;
00045 yuv = new YUV;
00046 PLUGIN_CONSTRUCTOR_MACRO
00047 }
00048
00049 BurnMain::~BurnMain()
00050 {
00051 PLUGIN_DESTRUCTOR_MACRO
00052
00053 if(buffer) delete [] buffer;
00054 if(burn_server) delete burn_server;
00055 if(effecttv) delete effecttv;
00056 if(yuv) delete yuv;
00057 }
00058
00059 char* BurnMain::plugin_title() { return N_("BurningTV"); }
00060 int BurnMain::is_realtime() { return 1; }
00061
00062
00063 NEW_PICON_MACRO(BurnMain)
00064 SHOW_GUI_MACRO(BurnMain, BurnThread)
00065 SET_STRING_MACRO(BurnMain)
00066 RAISE_WINDOW_MACRO(BurnMain)
00067
00068 int BurnMain::load_defaults()
00069 {
00070 return 0;
00071 }
00072
00073 int BurnMain::save_defaults()
00074 {
00075 return 0;
00076 }
00077
00078 void BurnMain::load_configuration()
00079 {
00080
00081 }
00082
00083
00084 void BurnMain::save_data(KeyFrame *keyframe)
00085 {
00086 }
00087
00088 void BurnMain::read_data(KeyFrame *keyframe)
00089 {
00090 }
00091
00092
00093
00094 #define MAXCOLOR 120
00095
00096 void BurnMain::HSItoRGB(double H,
00097 double S,
00098 double I,
00099 int *r,
00100 int *g,
00101 int *b,
00102 int color_model)
00103 {
00104 double T, Rv, Gv, Bv;
00105
00106 T = H;
00107 Rv = 1 + S * sin(T - 2 * M_PI / 3);
00108 Gv = 1 + S * sin(T);
00109 Bv = 1 + S * sin(T + 2 * M_PI / 3);
00110 T = 255.999 * I / 2;
00111
00112 *r = (int)CLIP(Rv * T, 0, 255);
00113 *g = (int)CLIP(Gv * T, 0, 255);
00114 *b = (int)CLIP(Bv * T, 0, 255);
00115 }
00116
00117
00118 void BurnMain::make_palette(int color_model)
00119 {
00120 int i, r, g, b;
00121
00122 for(i = 0; i < MAXCOLOR; i++)
00123 {
00124 HSItoRGB(4.6 - 1.5 * i / MAXCOLOR,
00125 (double)i / MAXCOLOR,
00126 (double)i / MAXCOLOR,
00127 &r,
00128 &g,
00129 &b,
00130 color_model);
00131 palette[0][i] = r;
00132 palette[1][i] = g;
00133 palette[2][i] = b;
00134
00135 }
00136
00137
00138 for(i = MAXCOLOR; i < 256; i++)
00139 {
00140 if(r < 255) r++;
00141 if(r < 255) r++;
00142 if(r < 255) r++;
00143 if(g < 255) g++;
00144 if(g < 255) g++;
00145 if(b < 255) b++;
00146 if(b < 255) b++;
00147 palette[0][i] = r;
00148 palette[1][i] = g;
00149 palette[2][i] = b;
00150
00151 }
00152 }
00153
00154
00155
00156
00157 int BurnMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00158 {
00159 this->input_ptr = input_ptr;
00160 this->output_ptr = output_ptr;
00161
00162 load_configuration();
00163
00164 if(!burn_server)
00165 {
00166 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
00167 buffer = (unsigned char *)new unsigned char[input_ptr->get_w() * input_ptr->get_h()];
00168 make_palette(input_ptr->get_color_model());
00169
00170 effecttv->image_set_threshold_y(config.threshold);
00171 total = 0;
00172
00173 burn_server = new BurnServer(this, 1, 1);
00174 }
00175
00176 if(total == 0)
00177 {
00178 bzero(buffer, input_ptr->get_w() * input_ptr->get_h());
00179 effecttv->image_bgset_y(input_ptr);
00180 }
00181 burn_server->process_packages();
00182
00183 total++;
00184
00185 return 0;
00186 }
00187
00188
00189
00190 BurnServer::BurnServer(BurnMain *plugin, int total_clients, int total_packages)
00191 : LoadServer(total_clients, total_packages)
00192 {
00193 this->plugin = plugin;
00194 }
00195
00196
00197 LoadClient* BurnServer::new_client()
00198 {
00199 return new BurnClient(this);
00200 }
00201
00202
00203
00204
00205 LoadPackage* BurnServer::new_package()
00206 {
00207 return new BurnPackage;
00208 }
00209
00210
00211
00212 void BurnServer::init_packages()
00213 {
00214 for(int i = 0; i < get_total_packages(); i++)
00215 {
00216 BurnPackage *package = (BurnPackage*)get_package(i);
00217 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
00218 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
00219 }
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229 BurnClient::BurnClient(BurnServer *server)
00230 : LoadClient(server)
00231 {
00232 this->plugin = server->plugin;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 #define BURN(type, components, is_yuv) \
00244 { \
00245 i = 1; \
00246 type **rows = (type**)input_rows; \
00247 for(y = 0; y < height; y++) \
00248 { \
00249 for(x = 1; x < width - 1; x++) \
00250 { \
00251 if(sizeof(type) == 4) \
00252 { \
00253 a1 = (int)(rows[0][i * components] * 0xff); \
00254 a2 = (int)(rows[0][i * components + 1] * 0xff); \
00255 a3 = (int)(rows[0][i * components + 2] * 0xff); \
00256 CLAMP(a1, 0, 0xff); \
00257 CLAMP(a2, 0, 0xff); \
00258 CLAMP(a3, 0, 0xff); \
00259 b1 = plugin->palette[0][plugin->buffer[i]]; \
00260 b2 = plugin->palette[1][plugin->buffer[i]]; \
00261 b3 = plugin->palette[2][plugin->buffer[i]]; \
00262 a1 += b1; \
00263 a2 += b2; \
00264 a3 += b3; \
00265 b1 = a1 & 0x100; \
00266 b2 = a2 & 0x100; \
00267 b3 = a3 & 0x100; \
00268 rows[0][i * components] = (type)(a1 | (b1 - (b1 >> 8))) / 0xff; \
00269 rows[0][i * components + 1] = (type)(a2 | (b2 - (b2 >> 8))) / 0xff; \
00270 rows[0][i * components + 2] = (type)(a3 | (b3 - (b3 >> 8))) / 0xff; \
00271 } \
00272 else \
00273 if(sizeof(type) == 2) \
00274 { \
00275 a1 = ((int)rows[0][i * components + 0]) >> 8; \
00276 a2 = ((int)rows[0][i * components + 1]) >> 8; \
00277 a3 = ((int)rows[0][i * components + 2]) >> 8; \
00278 b1 = plugin->palette[0][plugin->buffer[i]]; \
00279 b2 = plugin->palette[1][plugin->buffer[i]]; \
00280 b3 = plugin->palette[2][plugin->buffer[i]]; \
00281 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
00282 a1 += b1; \
00283 a2 += b2; \
00284 a3 += b3; \
00285 b1 = a1 & 0x100; \
00286 b2 = a2 & 0x100; \
00287 b3 = a3 & 0x100; \
00288 a1 = (a1 | (b1 - (b1 >> 8))); \
00289 a2 = (a2 | (b2 - (b2 >> 8))); \
00290 a3 = (a3 | (b3 - (b3 >> 8))); \
00291 if(is_yuv) \
00292 { \
00293 CLAMP(a1, 0, 0xff); \
00294 CLAMP(a2, 0, 0xff); \
00295 CLAMP(a3, 0, 0xff); \
00296 plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
00297 } \
00298 rows[0][i * components + 0] = a1 | (a1 << 8); \
00299 rows[0][i * components + 1] = a2 | (a2 << 8); \
00300 rows[0][i * components + 2] = a3 | (a3 << 8); \
00301 } \
00302 else \
00303 { \
00304 a1 = (int)rows[0][i * components + 0]; \
00305 a2 = (int)rows[0][i * components + 1]; \
00306 a3 = (int)rows[0][i * components + 2]; \
00307 b1 = plugin->palette[0][plugin->buffer[i]]; \
00308 b2 = plugin->palette[1][plugin->buffer[i]]; \
00309 b3 = plugin->palette[2][plugin->buffer[i]]; \
00310 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
00311 a1 += b1; \
00312 a2 += b2; \
00313 a3 += b3; \
00314 b1 = a1 & 0x100; \
00315 b2 = a2 & 0x100; \
00316 b3 = a3 & 0x100; \
00317 a1 = (a1 | (b1 - (b1 >> 8))); \
00318 a2 = (a2 | (b2 - (b2 >> 8))); \
00319 a3 = (a3 | (b3 - (b3 >> 8))); \
00320 if(is_yuv) \
00321 { \
00322 CLAMP(a1, 0, 0xff); \
00323 CLAMP(a2, 0, 0xff); \
00324 CLAMP(a3, 0, 0xff); \
00325 plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
00326 } \
00327 rows[0][i * components + 0] = a1; \
00328 rows[0][i * components + 1] = a2; \
00329 rows[0][i * components + 2] = a3; \
00330 } \
00331 i++; \
00332 } \
00333 i += 2; \
00334 } \
00335 }
00336
00337
00338
00339
00340 void BurnClient::process_package(LoadPackage *package)
00341 {
00342 BurnPackage *local_package = (BurnPackage*)package;
00343 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
00344 unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
00345 int width = plugin->input_ptr->get_w();
00346 int height = local_package->row2 - local_package->row1;
00347 unsigned char *diff;
00348 int pitch = width * plugin->input_ptr->get_bytes_per_pixel();
00349 int i, x, y;
00350 unsigned int v, w;
00351 int a1, b1, c1;
00352 int a2, b2, c2;
00353 int a3, b3, c3;
00354
00355
00356 diff = plugin->effecttv->image_bgsubtract_y(input_rows,
00357 plugin->input_ptr->get_color_model());
00358
00359 for(x = 1; x < width - 1; x++)
00360 {
00361 v = 0;
00362 for(y = 0; y < height - 1; y++)
00363 {
00364 w = diff[y * width + x];
00365 plugin->buffer[y * width + x] |= v ^ w;
00366 v = w;
00367 }
00368 }
00369
00370 for(x = 1; x < width - 1; x++)
00371 {
00372 w = 0;
00373 i = width + x;
00374
00375 for(y = 1; y < height; y++)
00376 {
00377 v = plugin->buffer[i];
00378
00379 if(v < plugin->config.decay)
00380 plugin->buffer[i - width] = 0;
00381 else
00382 plugin->buffer[i - width + EffectTV::fastrand() % 3 - 1] =
00383 v - (EffectTV::fastrand() & plugin->config.decay);
00384
00385 i += width;
00386 }
00387 }
00388
00389
00390
00391 switch(plugin->input_ptr->get_color_model())
00392 {
00393 case BC_RGB888:
00394 BURN(uint8_t, 3, 0);
00395 break;
00396 case BC_YUV888:
00397 BURN(uint8_t, 3, 1);
00398 break;
00399
00400 case BC_RGB_FLOAT:
00401 BURN(float, 3, 0);
00402 break;
00403
00404 case BC_RGBA_FLOAT:
00405 BURN(float, 4, 0);
00406 break;
00407
00408 case BC_RGBA8888:
00409 BURN(uint8_t, 4, 0);
00410 break;
00411 case BC_YUVA8888:
00412 BURN(uint8_t, 4, 1);
00413 break;
00414
00415 case BC_RGB161616:
00416 BURN(uint16_t, 3, 0);
00417 break;
00418 case BC_YUV161616:
00419 BURN(uint16_t, 3, 1);
00420 break;
00421
00422 case BC_RGBA16161616:
00423 BURN(uint16_t, 4, 0);
00424 break;
00425 case BC_YUVA16161616:
00426 BURN(uint16_t, 4, 1);
00427 break;
00428 }
00429
00430
00431 }
00432
00433
00434
00435 BurnPackage::BurnPackage()
00436 {
00437 }
00438
00439
00440