r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / holo / holo.C
blob0b06881c159744407e653106c5db8e99bf703b60
1 #include "clip.h"
2 #include "colormodels.h"
3 #include "filexml.h"
4 #include "picon_png.h"
5 #include "holo.h"
6 #include "holowindow.h"
7 #include "effecttv.h"
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
13 #include <libintl.h>
14 #define _(String) gettext(String)
15 #define gettext_noop(String) String
16 #define N_(String) gettext_noop (String)
18 PluginClient* new_plugin(PluginServer *server)
20         return new HoloMain(server);
33 HoloConfig::HoloConfig()
35         threshold = 40;
36         recycle = 1.0;
43 HoloMain::HoloMain(PluginServer *server)
44  : PluginVClient(server)
46         thread = 0;
47         defaults = 0;
48         effecttv = 0;
49         bgimage = 0;
50         do_reconfigure = 1;
51         load_defaults();
54 HoloMain::~HoloMain()
56         PLUGIN_DESTRUCTOR_MACRO
59         if(effecttv)
60         {
61                 delete holo_server;
62                 delete effecttv;
63         }
65         if(bgimage)
66                 delete bgimage;
69 char* HoloMain::plugin_title() { return _("HolographicTV"); }
70 int HoloMain::is_realtime() { return 1; }
72 VFrame* HoloMain::new_picon()
74         return new VFrame(picon_png);
77 int HoloMain::load_defaults()
79         return 0;
82 int HoloMain::save_defaults()
84         return 0;
87 void HoloMain::load_configuration()
92 void HoloMain::save_data(KeyFrame *keyframe)
96 void HoloMain::read_data(KeyFrame *keyframe)
100 void HoloMain::reconfigure()
102         do_reconfigure = 0;
104         effecttv->image_set_threshold_y(config.threshold);
108 #define ADD_FRAMES(type, components) \
109 { \
110         type **input_rows = (type**)input->get_rows(); \
111         type **output_rows = (type**)output->get_rows(); \
112         int w = input->get_w(); \
113         int h = input->get_h(); \
115         for(int i = 0; i < h; i++) \
116         { \
117                 type *output_row = (type*)output_rows[i]; \
118                 type *input_row = (type*)input_rows[i]; \
120                 for(int j = 0; j < w; j++) \
121                 { \
122                         for(int k = 0; k < components; k++) \
123                         { \
124                                 *output_row = (*input_row & *output_row) +  \
125                                         ((*input_row ^ *output_row) >> 1); \
126                                 output_row++; \
127                                 input_row++; \
128                         } \
129                 } \
130         } \
134 // Add input to output and store result in output
135 void HoloMain::add_frames(VFrame *output, VFrame *input)
137         switch(output->get_color_model())
138         {
139                 case BC_RGB888:
140                 case BC_YUV888:
141                         ADD_FRAMES(uint8_t, 3);
142                         break;
143                 case BC_RGBA8888:
144                 case BC_YUVA8888:
145                         ADD_FRAMES(uint8_t, 4);
146                         break;
147                 case BC_RGB161616:
148                 case BC_YUV161616:
149                         ADD_FRAMES(uint16_t, 3);
150                         break;
151                 case BC_RGBA16161616:
152                 case BC_YUVA16161616:
153                         ADD_FRAMES(uint16_t, 4);
154                         break;
155         }
158 void HoloMain::set_background()
161  * grab 4 frames and composite them to get a quality background image
162  */
163 total = 0;
165         switch(total)
166         {
167                 case 0:
168 /* step 1: grab frame-1 to buffer-1 */
169 //                      tmp = new VFrame(0, 
170 //                              input_ptr->get_w(), 
171 //                              input_ptr->get_h(),
172 //                              project_color_model);
173                         bgimage->copy_from(input_ptr);
174                         break;
176                 case 1:
177 /* step 2: add frame-2 to buffer-1 */
178                         add_frames(bgimage, input_ptr);
179                         break;
181                 case 2:
182 /* step 3: grab frame-3 to buffer-2 */
183                         tmp->copy_from(input_ptr);
184                         break;
186                 case 3:
187 /* step 4: add frame-4 to buffer-2 */
188                         add_frames(tmp, input_ptr);
192 /* step 5: add buffer-3 to buffer-1 */
193                         add_frames(bgimage, tmp);
195                         effecttv->image_bgset_y(bgimage);
198                         delete tmp;
199                         break;
200         }
204 int HoloMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
206 //printf("HoloMain::process_realtime 1\n");
207         this->input_ptr = input_ptr;
208         this->output_ptr = output_ptr;
213         load_configuration();
215 //printf("HoloMain::process_realtime 1\n");
218         if(do_reconfigure)
219         {
220                 if(!effecttv)
221                 {
222                         effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
223                         bgimage = new VFrame(0, 
224                                 input_ptr->get_w(), 
225                                 input_ptr->get_h(), 
226                                 input_ptr->get_color_model());
228                         for(int i = 0; i < 256; i++)
229                         {
230                                 noisepattern[i] = (i * i * i / 40000)* i / 256;
231                         }
233                         holo_server = new HoloServer(this, 1, 1);
234                 }
236                 reconfigure();
237         }
239 //printf("HoloMain::process_realtime 1\n");
240         set_background();
241 //printf("HoloMain::process_realtime 1\n");
242         
243         holo_server->process_packages();
244 //printf("HoloMain::process_realtime 1\n");
245         
246         total++;
247         if(total >= config.recycle * project_frame_rate)
248                 total = 0;
249 //printf("HoloMain::process_realtime 2\n");
251         return 0;
254 int HoloMain::show_gui()
256         load_configuration();
257         thread = new HoloThread(this);
258         thread->start();
259         return 0;
262 int HoloMain::set_string()
264         if(thread) thread->window->set_title(gui_string);
265         return 0;
268 void HoloMain::raise_window()
270         if(thread)
271         {
272                 thread->window->raise_window();
273                 thread->window->flush();
274         }
280 HoloServer::HoloServer(HoloMain *plugin, int total_clients, int total_packages)
281  : LoadServer(total_clients, total_packages)
282 // : LoadServer(1, 1)
284         this->plugin = plugin;
288 LoadClient* HoloServer::new_client() 
290         return new HoloClient(this);
296 LoadPackage* HoloServer::new_package() 
298         return new HoloPackage; 
303 void HoloServer::init_packages()
305         for(int i = 0; i < total_packages; i++)
306         {
307                 HoloPackage *package = (HoloPackage*)packages[i];
308                 package->row1 = plugin->input_ptr->get_h() / total_packages * i;
309                 package->row2 = package->row1 + plugin->input_ptr->get_h() / total_packages;
310                 if(i >= total_packages - 1)
311                         package->row2 = plugin->input_ptr->get_h();
312         }
322 HoloClient::HoloClient(HoloServer *server)
323  : LoadClient(server)
325         this->plugin = server->plugin;
326         phase = 0;
330 void HoloClient::process_package(LoadPackage *package)
332         int x, y;
333         int sx, sy;
334         HoloPackage *local_package = (HoloPackage*)package;
335         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
336         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
337         int width = plugin->input_ptr->get_w();
338         int height = local_package->row2 - local_package->row1;
339         unsigned char *diff;
340         uint32_t s, t;
341         int r, g, b;
343         diff = plugin->effecttv->image_diff_filter(plugin->effecttv->image_bgsubtract_y(input_rows, 
344                 plugin->input_ptr->get_color_model()));
346         diff += width;
347         output_rows++;
348         input_rows++;
352 #define STORE_PIXEL(type, components, dest, src) \
353 if(sizeof(type) == 2) \
354 { \
355         dest = (src[0] << 8) | \
356                 (src[1]) | \
357                 (src[2]) >> 8; \
358 } \
359 else \
360 { \
361         dest = (src[0] << 16) | \
362                 (src[1] << 8) | \
363                 src[2]; \
369 #define HOLO_CORE(type, components) \
370         for(y = 1; y < height - 1; y++) \
371         { \
372                 type *src = (type*)input_rows[y]; \
373                 type *bg = (type*)plugin->bgimage->get_rows()[y]; \
374                 type *dest = (type*)output_rows[y]; \
378                 if(((y + phase) & 0x7f) < 0x58)  \
379                 { \
380                         for(x = 0 ; x < width; x++)  \
381                         { \
382                                 if(*diff) \
383                                 { \
384                                         STORE_PIXEL(type, components, s, src); \
386                                         t = (s & 0xff) +  \
387                                                 ((s & 0xff00) >> 7) +  \
388                                                 ((s & 0xff0000) >> 16); \
389                                         t += plugin->noisepattern[EffectTV::fastrand() >> 24]; \
391                                         r = ((s & 0xff0000) >> 17) + t; \
392                                         g = ((s & 0xff00) >> 8) + t; \
393                                         b = (s & 0xff) + t; \
395                                         r = (r >> 1) - 100; \
396                                         g = (g >> 1) - 100; \
397                                         b = b >> 2; \
399                                         if(r < 20) r = 20; \
400                                         if(g < 20) g = 20; \
402                                         STORE_PIXEL(type, components, s, bg); \
404                                         r += (s & 0xff0000) >> 17; \
405                                         g += (s & 0xff00) >> 9; \
406                                         b += ((s & 0xff) >> 1) + 40; \
408                                         if(r > 255) r = 255; \
409                                         if(g > 255) g = 255; \
410                                         if(b > 255) b = 255; \
412                                         dest[0] = r; \
413                                         dest[1] = g; \
414                                         dest[2] = b; \
415                                         if(components == 4) dest[3] = src[3]; \
416                                 }  \
417                                 else  \
418                                 { \
419                                         dest[0] = bg[0]; \
420                                         dest[1] = bg[1]; \
421                                         dest[2] = bg[2]; \
422                                         if(components == 4) dest[3] = bg[3]; \
423                                 } \
425                                 diff++; \
426                                 src += components; \
427                                 dest += components; \
428                                 bg += components; \
429                         } \
430                 }  \
431                 else  \
432                 { \
433                         for(x = 0; x < width; x++) \
434                         { \
435                                 if(*diff) \
436                                 { \
437                                         STORE_PIXEL(type, components, s, src); \
440                                         t = (s & 0xff) + ((s & 0xff00) >> 6) + ((s & 0xff0000) >> 16); \
441                                         t += plugin->noisepattern[EffectTV::fastrand() >> 24]; \
443                                         r = ((s & 0xff0000) >> 16) + t; \
444                                         g = ((s & 0xff00) >> 8) + t; \
445                                         b = (s & 0xff) + t; \
447                                         r = (r >> 1) - 100; \
448                                         g = (g >> 1) - 100; \
449                                         b = b >> 2; \
451                                         if(r < 0) r = 0; \
452                                         if(g < 0) g = 0; \
454                                         STORE_PIXEL(type, components, s, bg); \
456                                         r += ((s & 0xff0000) >> 17) + 10; \
457                                         g += ((s & 0xff00) >> 9) + 10; \
458                                         b += ((s & 0xff) >> 1) + 40; \
460                                         if(r > 255) r = 255; \
461                                         if(g > 255) g = 255; \
462                                         if(b > 255) b = 255; \
464                                         dest[0] = r; \
465                                         dest[1] = g; \
466                                         dest[2] = b; \
467                                         if(components == 4) dest[3] = src[3]; \
468                                 }  \
469                                 else  \
470                                 { \
471                                         dest[0] = bg[0]; \
472                                         dest[1] = bg[1]; \
473                                         dest[2] = bg[2]; \
474                                         if(components == 4) dest[3] = bg[3]; \
475                                 } \
477                                 diff++; \
478                                 src += components; \
479                                 dest += components; \
480                                 bg += components; \
481                         } \
482                 } \
483         }
488         switch(plugin->input_ptr->get_color_model())
489         {
490                 case BC_RGB888:
491                 case BC_YUV888:
492                         HOLO_CORE(uint8_t, 3);
493                         break;
494                 case BC_RGBA8888:
495                 case BC_YUVA8888:
496                         HOLO_CORE(uint8_t, 4);
497                         break;
498                 case BC_RGB161616:
499                 case BC_YUV161616:
500                         HOLO_CORE(uint16_t, 3);
501                         break;
502                 case BC_RGBA16161616:
503                 case BC_YUVA16161616:
504                         HOLO_CORE(uint16_t, 4);
505                         break;
506         }
510         phase -= 37;
515 HoloPackage::HoloPackage()