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"
29 #include "burnwindow.h"
37 REGISTER_PLUGIN(BurnMain)
50 BurnConfig::BurnConfig()
57 BurnMain::BurnMain(PluginServer *server)
58 : PluginVClient(server)
71 if(buffer) delete [] buffer;
72 if(burn_server) delete burn_server;
73 if(effecttv) delete effecttv;
76 const char* BurnMain::plugin_title() { return N_("BurningTV"); }
77 int BurnMain::is_realtime() { return 1; }
80 NEW_WINDOW_MACRO(BurnMain, BurnWindow)
83 int BurnMain::load_configuration()
86 //printf("BurnMain::load_configuration %d\n", source_position);
90 void BurnMain::save_data(KeyFrame *keyframe)
94 void BurnMain::read_data(KeyFrame *keyframe)
102 void BurnMain::HSItoRGB(double H,
110 double T, Rv, Gv, Bv;
113 Rv = 1 + S * sin(T - 2 * M_PI / 3);
115 Bv = 1 + S * sin(T + 2 * M_PI / 3);
118 *r = (int)CLIP(Rv * T, 0, 255);
119 *g = (int)CLIP(Gv * T, 0, 255);
120 *b = (int)CLIP(Bv * T, 0, 255);
124 void BurnMain::make_palette(int color_model)
128 for(i = 0; i < MAXCOLOR; i++)
130 HSItoRGB(4.6 - 1.5 * i / MAXCOLOR,
131 (double)i / MAXCOLOR,
132 (double)i / MAXCOLOR,
140 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
144 for(i = MAXCOLOR; i < 256; i++)
156 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
163 int BurnMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
165 this->input_ptr = input_ptr;
166 this->output_ptr = output_ptr;
168 load_configuration();
172 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
173 buffer = (unsigned char *)new unsigned char[input_ptr->get_w() * input_ptr->get_h()];
174 make_palette(input_ptr->get_color_model());
176 effecttv->image_set_threshold_y(config.threshold);
179 burn_server = new BurnServer(this, 1, 1);
184 bzero(buffer, input_ptr->get_w() * input_ptr->get_h());
185 effecttv->image_bgset_y(input_ptr);
187 burn_server->process_packages();
190 // if(total >= config.recycle * project_frame_rate) total = 0;
196 BurnServer::BurnServer(BurnMain *plugin, int total_clients, int total_packages)
197 : LoadServer(total_clients, total_packages)
199 this->plugin = plugin;
203 LoadClient* BurnServer::new_client()
205 return new BurnClient(this);
211 LoadPackage* BurnServer::new_package()
213 return new BurnPackage;
218 void BurnServer::init_packages()
220 for(int i = 0; i < get_total_packages(); i++)
222 BurnPackage *package = (BurnPackage*)get_package(i);
223 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
224 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
235 BurnClient::BurnClient(BurnServer *server)
238 this->plugin = server->plugin;
249 #define BURN(type, components, is_yuv) \
252 type **rows = (type**)input_rows; \
253 for(y = 0; y < height; y++) \
255 for(x = 1; x < width - 1; x++) \
257 if(sizeof(type) == 4) \
259 a1 = (int)(rows[0][i * components] * 0xff); \
260 a2 = (int)(rows[0][i * components + 1] * 0xff); \
261 a3 = (int)(rows[0][i * components + 2] * 0xff); \
262 CLAMP(a1, 0, 0xff); \
263 CLAMP(a2, 0, 0xff); \
264 CLAMP(a3, 0, 0xff); \
265 b1 = plugin->palette[0][plugin->buffer[i]]; \
266 b2 = plugin->palette[1][plugin->buffer[i]]; \
267 b3 = plugin->palette[2][plugin->buffer[i]]; \
274 rows[0][i * components] = (type)(a1 | (b1 - (b1 >> 8))) / 0xff; \
275 rows[0][i * components + 1] = (type)(a2 | (b2 - (b2 >> 8))) / 0xff; \
276 rows[0][i * components + 2] = (type)(a3 | (b3 - (b3 >> 8))) / 0xff; \
279 if(sizeof(type) == 2) \
281 a1 = ((int)rows[0][i * components + 0]) >> 8; \
282 a2 = ((int)rows[0][i * components + 1]) >> 8; \
283 a3 = ((int)rows[0][i * components + 2]) >> 8; \
284 b1 = plugin->palette[0][plugin->buffer[i]]; \
285 b2 = plugin->palette[1][plugin->buffer[i]]; \
286 b3 = plugin->palette[2][plugin->buffer[i]]; \
287 if(is_yuv) YUV::yuv.yuv_to_rgb_8(a1, a2, a3); \
294 a1 = (a1 | (b1 - (b1 >> 8))); \
295 a2 = (a2 | (b2 - (b2 >> 8))); \
296 a3 = (a3 | (b3 - (b3 >> 8))); \
299 CLAMP(a1, 0, 0xff); \
300 CLAMP(a2, 0, 0xff); \
301 CLAMP(a3, 0, 0xff); \
302 YUV::yuv.rgb_to_yuv_8(a1, a2, a3); \
304 rows[0][i * components + 0] = a1 | (a1 << 8); \
305 rows[0][i * components + 1] = a2 | (a2 << 8); \
306 rows[0][i * components + 2] = a3 | (a3 << 8); \
310 a1 = (int)rows[0][i * components + 0]; \
311 a2 = (int)rows[0][i * components + 1]; \
312 a3 = (int)rows[0][i * components + 2]; \
313 b1 = plugin->palette[0][plugin->buffer[i]]; \
314 b2 = plugin->palette[1][plugin->buffer[i]]; \
315 b3 = plugin->palette[2][plugin->buffer[i]]; \
316 if(is_yuv) YUV::yuv.yuv_to_rgb_8(a1, a2, a3); \
323 a1 = (a1 | (b1 - (b1 >> 8))); \
324 a2 = (a2 | (b2 - (b2 >> 8))); \
325 a3 = (a3 | (b3 - (b3 >> 8))); \
328 CLAMP(a1, 0, 0xff); \
329 CLAMP(a2, 0, 0xff); \
330 CLAMP(a3, 0, 0xff); \
331 YUV::yuv.rgb_to_yuv_8(a1, a2, a3); \
333 rows[0][i * components + 0] = a1; \
334 rows[0][i * components + 1] = a2; \
335 rows[0][i * components + 2] = a3; \
346 void BurnClient::process_package(LoadPackage *package)
348 BurnPackage *local_package = (BurnPackage*)package;
349 unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
350 //unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
351 int width = plugin->input_ptr->get_w();
352 int height = local_package->row2 - local_package->row1;
354 //int pitch = width * plugin->input_ptr->get_bytes_per_pixel();
359 diff = plugin->effecttv->image_bgsubtract_y(input_rows,
360 plugin->input_ptr->get_color_model());
362 for(x = 1; x < width - 1; x++)
365 for(y = 0; y < height - 1; y++)
367 unsigned int w = diff[y * width + x];
368 plugin->buffer[y * width + x] |= v ^ w;
373 for(x = 1; x < width - 1; x++)
377 for(y = 1; y < height; y++)
379 int v = plugin->buffer[i];
381 if(v < plugin->config.decay)
382 plugin->buffer[i - width] = 0;
384 plugin->buffer[i - width + EffectTV::fastrand() % 3 - 1] =
385 v - (EffectTV::fastrand() & plugin->config.decay);
393 switch(plugin->input_ptr->get_color_model())
418 BURN(uint16_t, 3, 0);
421 BURN(uint16_t, 3, 1);
424 case BC_RGBA16161616:
425 BURN(uint16_t, 4, 0);
427 case BC_YUVA16161616:
428 BURN(uint16_t, 4, 1);
437 BurnPackage::BurnPackage()