#include "shared/disk_space_estimator.h"
#include "ffmpeg_capture.h"
#include "flags.h"
+#include "image_input.h"
#include "input_mapping.h"
#include "shared/metrics.h"
#include "mjpeg_encoder.h"
case PixelFormat_8BitBGRA:
glBindTexture(GL_TEXTURE_2D, userdata->tex_rgba[field]);
check_error();
- if (global_flags.can_disable_srgb_decoder) { // See the comments in tweaked_inputs.h.
- glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
- }
+ // NOTE: sRGB may be disabled by sRGBSwitchingFlatInput.
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
check_error();
break;
default:
num_cards(num_cards),
mixer_surface(create_surface(format)),
h264_encoder_surface(create_surface(format)),
- decklink_output_surface(create_surface(format))
+ decklink_output_surface(create_surface(format)),
+ image_update_surface(create_surface(format))
{
memcpy(ycbcr_interpretation, global_flags.ycbcr_interpretation, sizeof(ycbcr_interpretation));
CHECK(init_movit(MOVIT_SHADER_DIR, MOVIT_DEBUG_OFF));
check_error();
- // This nearly always should be true.
- global_flags.can_disable_srgb_decoder =
- epoxy_has_gl_extension("GL_EXT_texture_sRGB_decode") &&
- epoxy_has_gl_extension("GL_ARB_sampler_objects");
+ if (!epoxy_has_gl_extension("GL_EXT_texture_sRGB_decode") ||
+ !epoxy_has_gl_extension("GL_ARB_sampler_objects")) {
+ fprintf(stderr, "Nageru requires GL_EXT_texture_sRGB_decode and GL_ARB_sampler_objects to run.\n");
+ exit(1);
+ }
// Since we allow non-bouncing 4:2:2 YCbCrInputs, effective subpixel precision
// will be halved when sampling them, and we need to compensate here.
audio_mixer.reset(new AudioMixer(num_cards, video_inputs.size()));
httpd.add_endpoint("/channels", bind(&Mixer::get_channels_json, this), HTTPD::ALLOW_ALL_ORIGINS);
- for (int channel_idx = 2; channel_idx < theme->get_num_channels(); ++channel_idx) {
+ for (int channel_idx = 0; channel_idx < theme->get_num_channels(); ++channel_idx) {
char url[256];
- snprintf(url, sizeof(url), "/channels/%d/color", channel_idx);
- httpd.add_endpoint(url, bind(&Mixer::get_channel_color_http, this, unsigned(channel_idx)), HTTPD::ALLOW_ALL_ORIGINS);
+ snprintf(url, sizeof(url), "/channels/%d/color", channel_idx + 2);
+ httpd.add_endpoint(url, bind(&Mixer::get_channel_color_http, this, unsigned(channel_idx + 2)), HTTPD::ALLOW_ALL_ORIGINS);
}
// Start listening for clients only once VideoEncoder has written its header, if any.
}
output_jitter_history.register_metrics({{ "card", "output" }});
+
+ ImageInput::start_update_thread(image_update_surface);
}
Mixer::~Mixer()
{
+ ImageInput::end_update_thread();
+
if (mjpeg_encoder != nullptr) {
mjpeg_encoder->stop();
}
// we dropped. (may_have_dropped_last_frame is set whenever we
// trim the queue completely away, and cleared when we actually
// get a new frame.)
- ((CEFCapture *)card->capture.get())->request_new_frame();
+ ((CEFCapture *)card->capture.get())->request_new_frame(/*ignore_if_locked=*/true);
}
#endif
} else {