r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / videoscope / videoscope.C
blobd5df919adb384ca7e36c9fb4b104f96d47ac5d31
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "loadbalance.h"
7 #include "picon_png.h"
8 #include "plugincolors.h"
9 #include "pluginvclient.h"
10 #include "fonts.h"
11 #include "vframe.h"
13 #include <math.h>
14 #include <stdint.h>
15 #include <string.h>
18 #include <libintl.h>
19 #define _(String) gettext(String)
20 #define gettext_noop(String) String
21 #define N_(String) gettext_noop (String)
26 class VideoScopeEffect;
27 class VideoScopeEngine;
30 class VideoScopeConfig
32 public:
33         VideoScopeConfig();
36 class VideoScopeWaveform : public BC_SubWindow
38 public:
39         VideoScopeWaveform(VideoScopeEffect *plugin, 
40                 int x, 
41                 int y,
42                 int w,
43                 int h);
44         VideoScopeEffect *plugin;
48 class VideoScopeVectorscope : public BC_SubWindow
50 public:
51         VideoScopeVectorscope(VideoScopeEffect *plugin, 
52                 int x, 
53                 int y,
54                 int w,
55                 int h);
56         VideoScopeEffect *plugin;
59 class VideoScopeWindow : public BC_Window
61 public:
62         VideoScopeWindow(VideoScopeEffect *plugin, int x, int y);
63         ~VideoScopeWindow();
65         void calculate_sizes(int w, int h);
66         void create_objects();
67         int close_event();
68         int resize_event(int w, int h);
69         void allocate_bitmaps();
70         void draw_overlays();
72         VideoScopeEffect *plugin;
73         VideoScopeWaveform *waveform;
74         VideoScopeVectorscope *vectorscope;
75         BC_Bitmap *waveform_bitmap;
76         BC_Bitmap *vector_bitmap;
78         int vector_x, vector_y, vector_w, vector_h;
79         int wave_x, wave_y, wave_w, wave_h;
82 PLUGIN_THREAD_HEADER(VideoScopeEffect, VideoScopeThread, VideoScopeWindow)
87 class VideoScopePackage : public LoadPackage
89 public:
90         VideoScopePackage();
91         int row1, row2;
95 class VideoScopeUnit : public LoadClient
97 public:
98         VideoScopeUnit(VideoScopeEffect *plugin, VideoScopeEngine *server);
99         void process_package(LoadPackage *package);
100         VideoScopeEffect *plugin;
101         YUV yuv;
104 class VideoScopeEngine : public LoadServer
106 public:
107         VideoScopeEngine(VideoScopeEffect *plugin, int cpus);
108         ~VideoScopeEngine();
109         void init_packages();
110         LoadClient* new_client();
111         LoadPackage* new_package();
112         VideoScopeEffect *plugin;
115 class VideoScopeEffect : public PluginVClient
117 public:
118         VideoScopeEffect(PluginServer *server);
119         ~VideoScopeEffect();
121         int process_realtime(VFrame *input, VFrame *output);
122         int is_realtime();
123         char* plugin_title();
124         VFrame* new_picon();
125         int load_defaults();
126         int save_defaults();
127         int show_gui();
128         int set_string();
129         void raise_window();
130         void render_gui(void *input);
131         int load_configuration();
133         int w, h;
134         VFrame *input;
135         VideoScopeConfig config;
136         VideoScopeEngine *engine;
137         Defaults *defaults;
138         VideoScopeThread *thread;
153 VideoScopeConfig::VideoScopeConfig()
166 VideoScopeWaveform::VideoScopeWaveform(VideoScopeEffect *plugin, 
167                 int x, 
168                 int y,
169                 int w,
170                 int h)
171  : BC_SubWindow(x, y, w, h, BLACK)
173         this->plugin = plugin;
177 VideoScopeVectorscope::VideoScopeVectorscope(VideoScopeEffect *plugin, 
178                 int x, 
179                 int y,
180                 int w,
181                 int h)
182  : BC_SubWindow(x, y, w, h, BLACK)
184         this->plugin = plugin;
193 VideoScopeWindow::VideoScopeWindow(VideoScopeEffect *plugin, 
194         int x, 
195         int y)
196  : BC_Window(plugin->gui_string, 
197         x, 
198         y, 
199         plugin->w, 
200         plugin->h, 
201         50, 
202         50, 
203         1, 
204         0,
205         1,
206         BLACK)
208         this->plugin = plugin;
209         waveform_bitmap = 0;
210         vector_bitmap = 0;
213 VideoScopeWindow::~VideoScopeWindow()
216         if(waveform_bitmap) delete waveform_bitmap;
217         if(vector_bitmap) delete vector_bitmap;
220 void VideoScopeWindow::calculate_sizes(int w, int h)
222         wave_x = 30;
223         wave_y = 10;
224         wave_w = w / 2 - 5 - wave_x;
225         wave_h = h - 20 - wave_y;
226         vector_x = w / 2 + 30;
227         vector_y = 10;
228         vector_w = w - 10 - vector_x;
229         vector_h = h - 10 - vector_y;
232 void VideoScopeWindow::create_objects()
234         calculate_sizes(get_w(), get_h());
236         add_subwindow(waveform = new VideoScopeWaveform(plugin, wave_x, wave_y, wave_w, wave_h));
237         add_subwindow(vectorscope = new VideoScopeVectorscope(plugin, vector_x, vector_y, vector_w, vector_h));
238         allocate_bitmaps();
239         draw_overlays();
241         show_window();
242         flush();
243         
246 WINDOW_CLOSE_EVENT(VideoScopeWindow)
248 int VideoScopeWindow::resize_event(int w, int h)
251         clear_box(0, 0, w, h);
252         plugin->w = w;
253         plugin->h = h;
254         calculate_sizes(w, h);
255         waveform->reposition_window(wave_x, wave_y, wave_w, wave_h);
256         vectorscope->reposition_window(vector_x, vector_y, vector_w, vector_h);
257         waveform->clear_box(0, 0, wave_w, wave_h);
258         vectorscope->clear_box(0, 0, wave_w, wave_h);
259         allocate_bitmaps();
260         draw_overlays();
261         flash();
263         return 1;
266 void VideoScopeWindow::allocate_bitmaps()
268         if(waveform_bitmap) delete waveform_bitmap;
269         if(vector_bitmap) delete vector_bitmap;
271         waveform_bitmap = new_bitmap(wave_w, wave_h);
272         vector_bitmap = new_bitmap(vector_w, vector_h);
275 void VideoScopeWindow::draw_overlays()
277         set_color(GREEN);
278         set_font(SMALLFONT);
280         for(int i = 0; i <= 10; i++)
281         {
282                 int y = wave_h * i / 10;
283                 int text_y = y + wave_y + 10;
284                 int x = wave_x - 20;
285                 char string[BCTEXTLEN];
286                 sprintf(string, "%d", 100 - i * 10);
287                 draw_text(x, text_y, string);
288                 
289                 if(i > 0) waveform->draw_line(0, y, wave_w, y);
290         }
292 #define DIVISIONS 5
293         int radius = MIN(vector_w / 2, vector_h / 2);
294         for(int i = 0; i <= DIVISIONS; i++)
295         {
296                 int x = vector_w / 2 - radius * i / DIVISIONS;
297                 int y = vector_h / 2 - radius * i / DIVISIONS;
298                 int text_y = y + 20;
299                 int w = radius * i / DIVISIONS * 2;
300                 int h = radius * i / DIVISIONS * 2;
301                 char string[BCTEXTLEN];
302                 
303                 sprintf(string, "%d", i * 100 / DIVISIONS);
304                 draw_text(vector_x - 20, text_y, string);
305                 if(i > 0) vectorscope->draw_circle(x, y, w, h);
306         }
307         set_font(MEDIUMFONT);
309         waveform->flash();
310         vectorscope->flash();
311         flush();
321 PLUGIN_THREAD_OBJECT(VideoScopeEffect, VideoScopeThread, VideoScopeWindow)
327 REGISTER_PLUGIN(VideoScopeEffect)
334 VideoScopeEffect::VideoScopeEffect(PluginServer *server)
335  : PluginVClient(server)
337         engine = 0;
338         w = 640;
339         h = 260;
340         PLUGIN_CONSTRUCTOR_MACRO
343 VideoScopeEffect::~VideoScopeEffect()
345         PLUGIN_DESTRUCTOR_MACRO
347         if(engine) delete engine;
351 int VideoScopeEffect::is_realtime()
353         return 1;
356 char* VideoScopeEffect::plugin_title()
358         return _("VideoScope");
361 int VideoScopeEffect::load_configuration()
363         return 0;
366 NEW_PICON_MACRO(VideoScopeEffect)
368 SHOW_GUI_MACRO(VideoScopeEffect, VideoScopeThread)
370 RAISE_WINDOW_MACRO(VideoScopeEffect)
372 SET_STRING_MACRO(VideoScopeEffect)
374 int VideoScopeEffect::load_defaults()
376         char directory[BCTEXTLEN];
377 // set the default directory
378         sprintf(directory, "%svideoscope.rc", BCASTDIR);
380 // load the defaults
381         defaults = new Defaults(directory);
382         defaults->load();
384         w = defaults->get("W", w);
385         h = defaults->get("H", h);
386         return 0;
389 int VideoScopeEffect::save_defaults()
391         defaults->update("W", w);
392         defaults->update("H", h);
393         defaults->save();
394         return 0;
397 int VideoScopeEffect::process_realtime(VFrame *input, VFrame *output)
400         send_render_gui(input);
401 //printf("VideoScopeEffect::process_realtime 1\n");
402         if(input->get_rows()[0] != output->get_rows()[0])
403                 output->copy_from(input);
404         return 1;
407 void VideoScopeEffect::render_gui(void *input)
409         if(thread)
410         {
411                 VideoScopeWindow *window = thread->window;
412                 window->lock_window();
414 //printf("VideoScopeEffect::process_realtime 1\n");
415                 this->input = (VFrame*)input;
416 //printf("VideoScopeEffect::process_realtime 1\n");
419                 if(!engine)
420                 {
421                         engine = new VideoScopeEngine(this, 
422                                 (PluginClient::smp + 1));
423                 }
425 //printf("VideoScopeEffect::process_realtime 1 %d\n", PluginClient::smp);
426 // Clear bitmaps
427                 bzero(window->waveform_bitmap->get_data(), 
428                         window->waveform_bitmap->get_h() * 
429                         window->waveform_bitmap->get_bytes_per_line());
430                 bzero(window->vector_bitmap->get_data(), 
431                         window->vector_bitmap->get_h() * 
432                         window->vector_bitmap->get_bytes_per_line());
434                 engine->process_packages();
435 //printf("VideoScopeEffect::process_realtime 2\n");
436 //printf("VideoScopeEffect::process_realtime 1\n");
438                 window->waveform->draw_bitmap(window->waveform_bitmap, 
439                         1,
440                         0,
441                         0);
443 //printf("VideoScopeEffect::process_realtime 1\n");
444                 window->vectorscope->draw_bitmap(window->vector_bitmap, 
445                         1,
446                         0,
447                         0);
450                 window->draw_overlays();
453                 window->unlock_window();
454         }
461 VideoScopePackage::VideoScopePackage()
462  : LoadPackage()
471 VideoScopeUnit::VideoScopeUnit(VideoScopeEffect *plugin, 
472         VideoScopeEngine *server)
473  : LoadClient(server)
475         this->plugin = plugin;
479 #define INTENSITY(p) ((unsigned int)(((p)[0]) * 77+ \
480                                                                         ((p)[1] * 150) + \
481                                                                         ((p)[2] * 29)) >> 8)
484 static void draw_point(unsigned char **rows, int color_model, int x, int y, int r, int g, int b)
486         switch(color_model)
487         {
488                 case BC_BGR8888:
489                 {
490                         unsigned char *pixel = rows[y] + x * 4;
491                         pixel[0] = r;
492                         pixel[1] = g;
493                         pixel[2] = b;
494                         break;
495                 }
496                 case BC_BGR888:
497                         break;
498                 case BC_RGB565:
499                 {
500                         unsigned char *pixel = rows[y] + x * 2;
501                         pixel[0] = (r & 0xf8) | (g >> 5);
502                         pixel[1] = ((g & 0xfc) << 5) | (b >> 3);
503                         break;
504                 }
505                 case BC_BGR565:
506                         break;
507                 case BC_RGB8:
508                         break;
509         }
514 #define VIDEOSCOPE(type, max, components, use_yuv) \
515 { \
516         for(int i = pkg->row1; i < pkg->row2; i++) \
517         { \
518                 type *in_row = (type*)plugin->input->get_rows()[i]; \
519                 for(int j = 0; j < w; j++) \
520                 { \
521                         type *in_pixel = in_row + j * components; \
522                         float intensity; \
524 /* Analyze pixel */ \
525                         if(use_yuv) intensity = (float)*in_pixel / max; \
527                         float h, s, v; \
528                         int r, g, b; \
529                         if(use_yuv) \
530                         { \
531                                 if(max == 0xffff) \
532                                 { \
533                                         yuv.yuv_to_rgb_16(r, g, b, in_pixel[0], in_pixel[1], in_pixel[2]); \
534                                 } \
535                                 else \
536                                 { \
537                                         yuv.yuv_to_rgb_8(r, g, b, in_pixel[0], in_pixel[1], in_pixel[2]); \
538                                 } \
539                         } \
540                         else \
541                         { \
542                                 r = in_pixel[0]; \
543                                 g = in_pixel[1]; \
544                                 b = in_pixel[2]; \
545                         } \
547                         HSV::rgb_to_hsv((float)r / max, \
548                                         (float)g / max, \
549                                         (float)b / max, \
550                                         h, \
551                                         s, \
552                                         v); \
554                         if(max == 0xffff) \
555                         { \
556                                 r >>= 8; \
557                                 g >>= 8; \
558                                 b >>= 8; \
559                         } \
561 /* Calculate waveform */ \
562                         if(!use_yuv) intensity = v; \
563                         intensity = intensity * \
564                                 waveform_h; \
565                         int y = waveform_h - (int)intensity; \
566                         int x = j * waveform_w / w; \
567                         if(x >= 0 && x < waveform_w && y >= 0 && y < waveform_h) \
568                                 draw_point(waveform_rows, waveform_cmodel, x, y, 0xff, 0xff, 0xff); \
570 /* Calculate vectorscope */ \
571                         float adjacent = cos(h / 360 * 2 * M_PI); \
572                         float opposite = sin(h / 360 * 2 * M_PI); \
573                         x = (int)(vector_w / 2 +  \
574                                 adjacent * s * radius); \
576                         y = (int)(vector_h / 2 -  \
577                                 opposite * s * radius); \
580                         CLAMP(x, 0, vector_w - 1); \
581                         CLAMP(y, 0, vector_h - 1); \
582                         draw_point(vector_rows, vector_cmodel, x, y, r, g, b); \
584                 } \
585         } \
588 void VideoScopeUnit::process_package(LoadPackage *package)
590         VideoScopeWindow *window = plugin->thread->window;
591         VideoScopePackage *pkg = (VideoScopePackage*)package;
592         int w = plugin->input->get_w();
593         int h = plugin->input->get_h();
594         int waveform_h = window->waveform_bitmap->get_h();
595         int waveform_w = window->waveform_bitmap->get_w();
596         int waveform_cmodel = window->waveform_bitmap->get_color_model();
597         unsigned char **waveform_rows = window->waveform_bitmap->get_row_pointers();
598         int vector_h = window->vector_bitmap->get_h();
599         int vector_w = window->vector_bitmap->get_w();
600         int vector_cmodel = window->vector_bitmap->get_color_model();
601         unsigned char **vector_rows = window->vector_bitmap->get_row_pointers();
602         float radius = MIN(vector_w / 2, vector_h / 2);
604         switch(plugin->input->get_color_model())
605         {
606                 case BC_RGB888:
607                         VIDEOSCOPE(unsigned char, 0xff, 3, 0)
608                         break;
610                 case BC_YUV888:
611                         VIDEOSCOPE(unsigned char, 0xff, 3, 1)
612                         break;
614                 case BC_RGB161616:
615                         VIDEOSCOPE(uint16_t, 0xffff, 3, 0)
616                         break;
618                 case BC_YUV161616:
619                         VIDEOSCOPE(uint16_t, 0xffff, 3, 1)
620                         break;
622                 case BC_RGBA8888:
623                         VIDEOSCOPE(unsigned char, 0xff, 4, 0)
624                         break;
626                 case BC_YUVA8888:
627                         VIDEOSCOPE(unsigned char, 0xff, 4, 1)
628                         break;
630                 case BC_RGBA16161616:
631                         VIDEOSCOPE(uint16_t, 0xffff, 4, 0)
632                         break;
634                 case BC_YUVA16161616:
635                         VIDEOSCOPE(uint16_t, 0xffff, 4, 1)
636                         break;
637         }
645 VideoScopeEngine::VideoScopeEngine(VideoScopeEffect *plugin, int cpus)
646  : LoadServer(cpus, cpus)
648         this->plugin = plugin;
651 VideoScopeEngine::~VideoScopeEngine()
655 void VideoScopeEngine::init_packages()
657         int increment = plugin->input->get_h() / LoadServer::total_packages + 1;
658         int y = 0;
659         for(int i = 0; i < LoadServer::total_packages; i++)
660         {
661                 VideoScopePackage *pkg = (VideoScopePackage*)packages[i];
662                 pkg->row1 = y;
663                 pkg->row2 = y + increment;
664                 y += increment;
665                 if(pkg->row2 > plugin->input->get_h())
666                 {
667                         y = pkg->row2 = plugin->input->get_h();
668                 }
669         }
673 LoadClient* VideoScopeEngine::new_client()
675         return new VideoScopeUnit(plugin, this);
678 LoadPackage* VideoScopeEngine::new_package()
680         return new VideoScopePackage;