X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=analyzer.cpp;fp=analyzer.cpp;h=353229ee730f10c6562257fd679b1a58842d613a;hb=66421f32d0f2e8a8bdb86b3f381a6ebb6426cf0c;hp=0000000000000000000000000000000000000000;hpb=5ac91302c4138f21989ce1103ff42a9209e2f90f;p=nageru diff --git a/analyzer.cpp b/analyzer.cpp new file mode 100644 index 0000000..353229e --- /dev/null +++ b/analyzer.cpp @@ -0,0 +1,145 @@ +#include "analyzer.h" + +#include +#include + +#include +#include + +#include "context.h" +#include "flags.h" +#include "mixer.h" +#include "ui_analyzer.h" + +using namespace std; + +Analyzer::Analyzer() + : ui(new Ui::Analyzer) +{ + ui->setupUi(this); + + //connect(ui->button_box, &QDialogButtonBox::accepted, [this]{ this->close(); }); + + ui->input_box->addItem("Live", Mixer::OUTPUT_LIVE); + ui->input_box->addItem("Preview", Mixer::OUTPUT_PREVIEW); + unsigned num_channels = global_mixer->get_num_channels(); + for (unsigned channel_idx = 0; channel_idx < num_channels; ++channel_idx) { + Mixer::Output channel = static_cast(Mixer::OUTPUT_INPUT0 + channel_idx); + string name = global_mixer->get_channel_name(channel); + ui->input_box->addItem(QString::fromStdString(name), channel); + } + + connect(ui->grab_btn, &QPushButton::clicked, bind(&Analyzer::grab_clicked, this)); + //ui->display->set_output(Mixer::OUTPUT_LIVE); + surface = create_surface(QSurfaceFormat::defaultFormat()); + context = create_context(surface); + + if (!make_current(context, surface)) { + printf("oops\n"); + exit(1); + } + + glGenBuffers(1, &pbo); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo); + glBufferData(GL_PIXEL_PACK_BUFFER_ARB, global_flags.width * global_flags.height * 4, NULL, GL_STREAM_READ); +} + +Analyzer::~Analyzer() +{ + if (!make_current(context, surface)) { + printf("oops\n"); + exit(1); + } + glDeleteBuffers(1, &pbo); + check_error(); + if (resource_pool != nullptr) { + resource_pool->clean_context(); + } + delete_context(context); + delete surface; // TODO? +} + +void Analyzer::grab_clicked() +{ + Mixer::Output channel = static_cast(ui->input_box->currentData().value()); + + if (!make_current(context, surface)) { + printf("oops\n"); + exit(1); + } + + Mixer::DisplayFrame frame; + if (!global_mixer->get_display_frame(channel, &frame)) { + printf("Not ready yet\n"); + return; + } + + // Set up an FBO to render into. + if (resource_pool == nullptr) { + resource_pool = frame.chain->get_resource_pool(); + } else { + assert(resource_pool == frame.chain->get_resource_pool()); + } + GLuint fbo_tex = resource_pool->create_2d_texture(GL_RGBA8, global_flags.width, global_flags.height); + check_error(); + GLuint fbo = resource_pool->create_fbo(fbo_tex); + check_error(); + + glWaitSync(frame.ready_fence.get(), /*flags=*/0, GL_TIMEOUT_IGNORED); + check_error(); + frame.setup_chain(); + check_error(); + glDisable(GL_FRAMEBUFFER_SRGB); + check_error(); + frame.chain->render_to_fbo(fbo, global_flags.width, global_flags.height); + check_error(); + + // Read back to memory. + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + check_error(); + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo); + check_error(); + glReadPixels(0, 0, global_flags.width, global_flags.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER_OFFSET(0)); + check_error(); + + unsigned char *buf = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); + check_error(); + + int r_hist[256] = {0}, g_hist[256] = {0}, b_hist[256] = {0}; + const unsigned char *ptr = buf; + for (int y = 0; y < global_flags.width; ++y) { + for (int x = 0; x < global_flags.height; ++x) { + uint8_t b = *ptr++; + uint8_t g = *ptr++; + uint8_t r = *ptr++; + uint8_t a = *ptr++; + + ++r_hist[r]; + ++g_hist[g]; + ++b_hist[b]; + } + } + + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + check_error(); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + check_error(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + check_error(); + + printf("R hist:"); + for (unsigned i = 0; i < 256; ++i) { printf(" %d", r_hist[i]); } + printf("\n"); + printf("G hist:"); + for (unsigned i = 0; i < 256; ++i) { printf(" %d", g_hist[i]); } + printf("\n"); + printf("B hist:"); + for (unsigned i = 0; i < 256; ++i) { printf(" %d", b_hist[i]); } + printf("\n"); + + resource_pool->release_2d_texture(fbo_tex); + check_error(); + resource_pool->release_fbo(fbo); + check_error(); +} +