1 #include "bcdisplayinfo.h"
7 #include "loadbalance.h"
9 #include "plugincolors.h"
10 #include "pluginvclient.h"
21 #define FLOAT_MIN -0.1
23 #define WAVEFORM_DIVISIONS 12
24 #define VECTORSCOPE_DIVISIONS 12
27 class VideoScopeEffect;
28 class VideoScopeEngine;
31 class VideoScopeConfig
37 class VideoScopeWaveform : public BC_SubWindow
40 VideoScopeWaveform(VideoScopeEffect *plugin,
45 VideoScopeEffect *plugin;
49 class VideoScopeVectorscope : public BC_SubWindow
52 VideoScopeVectorscope(VideoScopeEffect *plugin,
57 VideoScopeEffect *plugin;
60 class VideoScopeWindow : public BC_Window
63 VideoScopeWindow(VideoScopeEffect *plugin, int x, int y);
66 void calculate_sizes(int w, int h);
67 void create_objects();
69 int resize_event(int w, int h);
70 void allocate_bitmaps();
73 VideoScopeEffect *plugin;
74 VideoScopeWaveform *waveform;
75 VideoScopeVectorscope *vectorscope;
76 BC_Bitmap *waveform_bitmap;
77 BC_Bitmap *vector_bitmap;
79 int vector_x, vector_y, vector_w, vector_h;
80 int wave_x, wave_y, wave_w, wave_h;
83 PLUGIN_THREAD_HEADER(VideoScopeEffect, VideoScopeThread, VideoScopeWindow)
88 class VideoScopePackage : public LoadPackage
96 class VideoScopeUnit : public LoadClient
99 VideoScopeUnit(VideoScopeEffect *plugin, VideoScopeEngine *server);
100 void process_package(LoadPackage *package);
101 VideoScopeEffect *plugin;
105 class VideoScopeEngine : public LoadServer
108 VideoScopeEngine(VideoScopeEffect *plugin, int cpus);
110 void init_packages();
111 LoadClient* new_client();
112 LoadPackage* new_package();
113 VideoScopeEffect *plugin;
116 class VideoScopeEffect : public PluginVClient
119 VideoScopeEffect(PluginServer *server);
122 int process_realtime(VFrame *input, VFrame *output);
124 char* plugin_title();
131 void render_gui(void *input);
132 int load_configuration();
136 VideoScopeConfig config;
137 VideoScopeEngine *engine;
139 VideoScopeThread *thread;
154 VideoScopeConfig::VideoScopeConfig()
167 VideoScopeWaveform::VideoScopeWaveform(VideoScopeEffect *plugin,
172 : BC_SubWindow(x, y, w, h, BLACK)
174 this->plugin = plugin;
178 VideoScopeVectorscope::VideoScopeVectorscope(VideoScopeEffect *plugin,
183 : BC_SubWindow(x, y, w, h, BLACK)
185 this->plugin = plugin;
194 VideoScopeWindow::VideoScopeWindow(VideoScopeEffect *plugin,
197 : BC_Window(plugin->gui_string,
209 this->plugin = plugin;
214 VideoScopeWindow::~VideoScopeWindow()
217 if(waveform_bitmap) delete waveform_bitmap;
218 if(vector_bitmap) delete vector_bitmap;
221 void VideoScopeWindow::calculate_sizes(int w, int h)
225 wave_w = w / 2 - 5 - wave_x;
226 wave_h = h - 20 - wave_y;
227 vector_x = w / 2 + 30;
229 vector_w = w - 10 - vector_x;
230 vector_h = h - 10 - vector_y;
233 void VideoScopeWindow::create_objects()
235 calculate_sizes(get_w(), get_h());
237 add_subwindow(waveform = new VideoScopeWaveform(plugin,
242 add_subwindow(vectorscope = new VideoScopeVectorscope(plugin,
255 WINDOW_CLOSE_EVENT(VideoScopeWindow)
257 int VideoScopeWindow::resize_event(int w, int h)
260 clear_box(0, 0, w, h);
263 calculate_sizes(w, h);
264 waveform->reposition_window(wave_x, wave_y, wave_w, wave_h);
265 vectorscope->reposition_window(vector_x, vector_y, vector_w, vector_h);
266 waveform->clear_box(0, 0, wave_w, wave_h);
267 vectorscope->clear_box(0, 0, wave_w, wave_h);
275 void VideoScopeWindow::allocate_bitmaps()
277 if(waveform_bitmap) delete waveform_bitmap;
278 if(vector_bitmap) delete vector_bitmap;
280 waveform_bitmap = new_bitmap(wave_w, wave_h);
281 vector_bitmap = new_bitmap(vector_w, vector_h);
284 void VideoScopeWindow::draw_overlays()
290 for(int i = 0; i <= WAVEFORM_DIVISIONS; i++)
292 int y = wave_h * i / WAVEFORM_DIVISIONS;
293 int text_y = y + wave_y + get_text_ascent(SMALLFONT) / 2;
295 char string[BCTEXTLEN];
296 sprintf(string, "%d",
298 i * (FLOAT_MAX - FLOAT_MIN) / WAVEFORM_DIVISIONS) * 100));
299 draw_text(x, text_y, string);
301 waveform->draw_line(0,
302 CLAMP(y, 0, waveform->get_h() - 1),
304 CLAMP(y, 0, waveform->get_h() - 1));
305 //waveform->draw_rectangle(0, 0, wave_w, wave_h);
310 // Vectorscope overlay
311 int radius = MIN(vector_w / 2, vector_h / 2);
312 for(int i = 1; i <= VECTORSCOPE_DIVISIONS - 1; i += 2)
314 int x = vector_w / 2 - radius * i / VECTORSCOPE_DIVISIONS;
315 int y = vector_h / 2 - radius * i / VECTORSCOPE_DIVISIONS;
316 int text_x = vector_x - 20;
317 int text_y = y + vector_y + get_text_ascent(SMALLFONT) / 2;
318 int w = radius * i / VECTORSCOPE_DIVISIONS * 2;
319 int h = radius * i / VECTORSCOPE_DIVISIONS * 2;
320 char string[BCTEXTLEN];
322 sprintf(string, "%d",
324 (FLOAT_MAX - FLOAT_MIN) / VECTORSCOPE_DIVISIONS * i) * 100));
325 draw_text(text_x, text_y, string);
326 vectorscope->draw_circle(x, y, w, h);
327 //vectorscope->draw_rectangle(0, 0, vector_w, vector_h);
329 // vectorscope->draw_circle(vector_w / 2 - radius,
330 // vector_h / 2 - radius,
333 set_font(MEDIUMFONT);
336 vectorscope->flash();
347 PLUGIN_THREAD_OBJECT(VideoScopeEffect, VideoScopeThread, VideoScopeWindow)
353 REGISTER_PLUGIN(VideoScopeEffect)
360 VideoScopeEffect::VideoScopeEffect(PluginServer *server)
361 : PluginVClient(server)
366 PLUGIN_CONSTRUCTOR_MACRO
369 VideoScopeEffect::~VideoScopeEffect()
371 PLUGIN_DESTRUCTOR_MACRO
373 if(engine) delete engine;
378 char* VideoScopeEffect::plugin_title() { return N_("VideoScope"); }
379 int VideoScopeEffect::is_realtime() { return 1; }
381 int VideoScopeEffect::load_configuration()
386 NEW_PICON_MACRO(VideoScopeEffect)
388 SHOW_GUI_MACRO(VideoScopeEffect, VideoScopeThread)
390 RAISE_WINDOW_MACRO(VideoScopeEffect)
392 SET_STRING_MACRO(VideoScopeEffect)
394 int VideoScopeEffect::load_defaults()
396 char directory[BCTEXTLEN];
397 // set the default directory
398 sprintf(directory, "%svideoscope.rc", BCASTDIR);
401 defaults = new Defaults(directory);
404 w = defaults->get("W", w);
405 h = defaults->get("H", h);
409 int VideoScopeEffect::save_defaults()
411 defaults->update("W", w);
412 defaults->update("H", h);
417 int VideoScopeEffect::process_realtime(VFrame *input, VFrame *output)
420 send_render_gui(input);
421 //printf("VideoScopeEffect::process_realtime 1\n");
422 if(input->get_rows()[0] != output->get_rows()[0])
423 output->copy_from(input);
427 void VideoScopeEffect::render_gui(void *input)
431 VideoScopeWindow *window = thread->window;
432 window->lock_window();
434 //printf("VideoScopeEffect::process_realtime 1\n");
435 this->input = (VFrame*)input;
436 //printf("VideoScopeEffect::process_realtime 1\n");
441 engine = new VideoScopeEngine(this,
442 (PluginClient::smp + 1));
445 //printf("VideoScopeEffect::process_realtime 1 %d\n", PluginClient::smp);
447 bzero(window->waveform_bitmap->get_data(),
448 window->waveform_bitmap->get_h() *
449 window->waveform_bitmap->get_bytes_per_line());
450 bzero(window->vector_bitmap->get_data(),
451 window->vector_bitmap->get_h() *
452 window->vector_bitmap->get_bytes_per_line());
454 engine->process_packages();
455 //printf("VideoScopeEffect::process_realtime 2\n");
456 //printf("VideoScopeEffect::process_realtime 1\n");
458 window->waveform->draw_bitmap(window->waveform_bitmap,
463 //printf("VideoScopeEffect::process_realtime 1\n");
464 window->vectorscope->draw_bitmap(window->vector_bitmap,
470 window->draw_overlays();
473 window->unlock_window();
481 VideoScopePackage::VideoScopePackage()
491 VideoScopeUnit::VideoScopeUnit(VideoScopeEffect *plugin,
492 VideoScopeEngine *server)
495 this->plugin = plugin;
499 #define INTENSITY(p) ((unsigned int)(((p)[0]) * 77+ \
504 static void draw_point(unsigned char **rows,
516 unsigned char *pixel = rows[y] + x * 4;
526 unsigned char *pixel = rows[y] + x * 2;
527 pixel[0] = (r & 0xf8) | (g >> 5);
528 pixel[1] = ((g & 0xfc) << 5) | (b >> 3);
540 #define VIDEOSCOPE(type, temp_type, max, components, use_yuv) \
542 for(int i = pkg->row1; i < pkg->row2; i++) \
544 type *in_row = (type*)plugin->input->get_rows()[i]; \
545 for(int j = 0; j < w; j++) \
547 type *in_pixel = in_row + j * components; \
550 /* Analyze pixel */ \
551 if(use_yuv) intensity = (float)*in_pixel / max; \
557 if(sizeof(type) == 2) \
559 yuv.yuv_to_rgb_16(r, \
568 yuv.yuv_to_rgb_8(r, \
583 HSV::rgb_to_hsv((float)r / max, \
590 /* Calculate waveform */ \
591 if(!use_yuv) intensity = v; \
592 intensity = (intensity - FLOAT_MIN) / (FLOAT_MAX - FLOAT_MIN) * \
594 int y = waveform_h - (int)intensity; \
595 int x = j * waveform_w / w; \
596 if(x >= 0 && x < waveform_w && y >= 0 && y < waveform_h) \
597 draw_point(waveform_rows, \
605 /* Calculate vectorscope */ \
606 float adjacent = cos(h / 360 * 2 * M_PI); \
607 float opposite = sin(h / 360 * 2 * M_PI); \
608 x = (int)(vector_w / 2 + \
609 adjacent * (s - FLOAT_MIN) / (FLOAT_MAX - FLOAT_MIN) * radius); \
611 y = (int)(vector_h / 2 - \
612 opposite * (s - FLOAT_MIN) / (FLOAT_MAX - FLOAT_MIN) * radius); \
615 CLAMP(x, 0, vector_w - 1); \
616 CLAMP(y, 0, vector_h - 1); \
617 if(sizeof(type) == 2) \
624 if(sizeof(type) == 4) \
626 r = CLIP(r, 0, 1) * 0xff; \
627 g = CLIP(g, 0, 1) * 0xff; \
628 b = CLIP(b, 0, 1) * 0xff; \
631 draw_point(vector_rows, \
643 void VideoScopeUnit::process_package(LoadPackage *package)
645 VideoScopeWindow *window = plugin->thread->window;
646 VideoScopePackage *pkg = (VideoScopePackage*)package;
647 int w = plugin->input->get_w();
648 int h = plugin->input->get_h();
649 int waveform_h = window->wave_h;
650 int waveform_w = window->wave_w;
651 int waveform_cmodel = window->waveform_bitmap->get_color_model();
652 unsigned char **waveform_rows = window->waveform_bitmap->get_row_pointers();
653 int vector_h = window->vector_bitmap->get_h();
654 int vector_w = window->vector_bitmap->get_w();
655 int vector_cmodel = window->vector_bitmap->get_color_model();
656 unsigned char **vector_rows = window->vector_bitmap->get_row_pointers();
657 float radius = MIN(vector_w / 2, vector_h / 2);
659 switch(plugin->input->get_color_model())
662 VIDEOSCOPE(unsigned char, int, 0xff, 3, 0)
666 VIDEOSCOPE(float, float, 1, 3, 0)
670 VIDEOSCOPE(unsigned char, int, 0xff, 3, 1)
674 VIDEOSCOPE(uint16_t, int, 0xffff, 3, 0)
678 VIDEOSCOPE(uint16_t, int, 0xffff, 3, 1)
682 VIDEOSCOPE(unsigned char, int, 0xff, 4, 0)
686 VIDEOSCOPE(float, float, 1, 4, 0)
690 VIDEOSCOPE(unsigned char, int, 0xff, 4, 1)
693 case BC_RGBA16161616:
694 VIDEOSCOPE(uint16_t, int, 0xffff, 4, 0)
697 case BC_YUVA16161616:
698 VIDEOSCOPE(uint16_t, int, 0xffff, 4, 1)
708 VideoScopeEngine::VideoScopeEngine(VideoScopeEffect *plugin, int cpus)
709 : LoadServer(cpus, cpus)
711 this->plugin = plugin;
714 VideoScopeEngine::~VideoScopeEngine()
718 void VideoScopeEngine::init_packages()
720 for(int i = 0; i < LoadServer::total_packages; i++)
722 VideoScopePackage *pkg = (VideoScopePackage*)packages[i];
723 pkg->row1 = plugin->input->get_h() * i / LoadServer::total_packages;
724 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::total_packages;
729 LoadClient* VideoScopeEngine::new_client()
731 return new VideoScopeUnit(plugin, this);
734 LoadPackage* VideoScopeEngine::new_package()
736 return new VideoScopePackage;