3 #include <QDialogButtonBox>
7 #include <movit/resource_pool.h>
8 #include <movit/util.h>
13 #include "ui_analyzer.h"
18 : ui(new Ui::Analyzer),
19 grabbed_image(global_flags.width, global_flags.height, QImage::Format_ARGB32_Premultiplied)
23 //connect(ui->button_box, &QDialogButtonBox::accepted, [this]{ this->close(); });
25 ui->input_box->addItem("Live", Mixer::OUTPUT_LIVE);
26 ui->input_box->addItem("Preview", Mixer::OUTPUT_PREVIEW);
27 unsigned num_channels = global_mixer->get_num_channels();
28 for (unsigned channel_idx = 0; channel_idx < num_channels; ++channel_idx) {
29 Mixer::Output channel = static_cast<Mixer::Output>(Mixer::OUTPUT_INPUT0 + channel_idx);
30 string name = global_mixer->get_channel_name(channel);
31 ui->input_box->addItem(QString::fromStdString(name), channel);
34 connect(ui->grab_btn, &QPushButton::clicked, bind(&Analyzer::grab_clicked, this));
35 connect(ui->input_box, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), bind(&Analyzer::signal_changed, this));
37 ui->grabbed_frame_label->installEventFilter(this);
39 surface = create_surface(QSurfaceFormat::defaultFormat());
40 context = create_context(surface);
42 if (!make_current(context, surface)) {
47 glGenBuffers(1, &pbo);
48 glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
49 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, global_flags.width * global_flags.height * 4, NULL, GL_STREAM_READ);
54 if (!make_current(context, surface)) {
58 glDeleteBuffers(1, &pbo);
60 if (resource_pool != nullptr) {
61 resource_pool->clean_context();
63 delete_context(context);
64 delete surface; // TODO?
67 void Analyzer::grab_clicked()
69 Mixer::Output channel = static_cast<Mixer::Output>(ui->input_box->currentData().value<int>());
71 if (!make_current(context, surface)) {
76 Mixer::DisplayFrame frame;
77 if (!global_mixer->get_display_frame(channel, &frame)) {
78 printf("Not ready yet\n");
82 // Set up an FBO to render into.
83 if (resource_pool == nullptr) {
84 resource_pool = frame.chain->get_resource_pool();
86 assert(resource_pool == frame.chain->get_resource_pool());
88 GLuint fbo_tex = resource_pool->create_2d_texture(GL_RGBA8, global_flags.width, global_flags.height);
90 GLuint fbo = resource_pool->create_fbo(fbo_tex);
93 glWaitSync(frame.ready_fence.get(), /*flags=*/0, GL_TIMEOUT_IGNORED);
97 glDisable(GL_FRAMEBUFFER_SRGB);
99 frame.chain->render_to_fbo(fbo, global_flags.width, global_flags.height);
102 // Read back to memory.
103 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
105 glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
107 glReadPixels(0, 0, global_flags.width, global_flags.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER_OFFSET(0));
110 unsigned char *buf = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
113 size_t pitch = global_flags.width * 4;
114 for (int y = 0; y < global_flags.height; ++y) {
115 memcpy(grabbed_image.scanLine(global_flags.height - y - 1), buf + y * pitch, pitch);
119 pixmap.convertFromImage(grabbed_image);
120 ui->grabbed_frame_label->setPixmap(pixmap);
122 int r_hist[256] = {0}, g_hist[256] = {0}, b_hist[256] = {0};
123 const unsigned char *ptr = buf;
124 for (int i = 0; i < global_flags.height * global_flags.width; ++i) {
135 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
137 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
139 glBindFramebuffer(GL_FRAMEBUFFER, 0);
143 for (unsigned i = 0; i < 256; ++i) { printf(" %d", r_hist[i]); }
146 for (unsigned i = 0; i < 256; ++i) { printf(" %d", g_hist[i]); }
149 for (unsigned i = 0; i < 256; ++i) { printf(" %d", b_hist[i]); }
152 resource_pool->release_2d_texture(fbo_tex);
154 resource_pool->release_fbo(fbo);
158 void Analyzer::signal_changed()
160 Mixer::Output channel = static_cast<Mixer::Output>(ui->input_box->currentData().value<int>());
161 ui->display->set_output(channel);
164 bool Analyzer::eventFilter(QObject *watched, QEvent *event)
166 if (event->type() == QEvent::MouseMove &&
167 watched->isWidgetType()) {
168 const QMouseEvent *mouse_event = (QMouseEvent *)event;
169 const QPixmap *pixmap = ui->grabbed_frame_label->pixmap();
170 if (pixmap != nullptr) {
171 int x = lrint(mouse_event->x() * double(pixmap->width()) / ui->grabbed_frame_label->width());
172 int y = lrint(mouse_event->y() * double(pixmap->height()) / ui->grabbed_frame_label->height());
173 x = std::min(x, pixmap->width() - 1);
174 y = std::min(y, pixmap->height() - 1);
175 QRgb pixel = grabbed_image.pixel(x, y);
176 ui->red_label->setText(QString::fromStdString(to_string(qRed(pixel))));
177 ui->green_label->setText(QString::fromStdString(to_string(qGreen(pixel))));
178 ui->blue_label->setText(QString::fromStdString(to_string(qBlue(pixel))));
181 snprintf(buf, sizeof(buf), "#%02x%02x%02x", qRed(pixel), qGreen(pixel), qBlue(pixel));
182 ui->hex_label->setText(buf);