When setting up a new frame, we'd set LiveInputWrapper state
(ie., which textures should FlatInput girender from) for all
chains, even preview chains which were just about to get rendered.
Those could then render from the wrong texture number -- and worse,
that texture was still in the process of being uploaded, causing
corrupted display.
There are probably still concurrency bugs left here, but this was
the biggest and most annoying one.
theme_main_chain.setup_chain();
//theme_main_chain.chain->enable_phase_timing(true);
theme_main_chain.setup_chain();
//theme_main_chain.chain->enable_phase_timing(true);
- // The theme can't (or at least shouldn't!) call connect_signal() on
- // each FFmpeg or CEF input, so we'll do it here.
- for (const pair<LiveInputWrapper *, FFmpegCapture *> &conn : theme->get_video_signal_connections()) {
- conn.first->connect_signal_raw(conn.second->get_card_index(), input_state);
- }
-#ifdef HAVE_CEF
- for (const pair<LiveInputWrapper *, CEFCapture *> &conn : theme->get_html_signal_connections()) {
- conn.first->connect_signal_raw(conn.second->get_card_index(), input_state);
- }
-#endif
-
// If HDMI/SDI output is active and the user has requested auto mode,
// its mode overrides the existing Y'CbCr setting for the chain.
YCbCrLumaCoefficients ycbcr_output_coefficients;
// If HDMI/SDI output is active and the user has requested auto mode,
// its mode overrides the existing Y'CbCr setting for the chain.
YCbCrLumaCoefficients ycbcr_output_coefficients;
if (ret == 1) {
Theme *theme = get_theme_updata(L);
LiveInputWrapper **live_input = (LiveInputWrapper **)lua_touserdata(L, -1);
if (ret == 1) {
Theme *theme = get_theme_updata(L);
LiveInputWrapper **live_input = (LiveInputWrapper **)lua_touserdata(L, -1);
- theme->register_video_signal_connection(*live_input, *capture);
+ theme->register_video_signal_connection(chain, *live_input, *capture);
if (ret == 1) {
Theme *theme = get_theme_updata(L);
LiveInputWrapper **live_input = (LiveInputWrapper **)lua_touserdata(L, -1);
if (ret == 1) {
Theme *theme = get_theme_updata(L);
LiveInputWrapper **live_input = (LiveInputWrapper **)lua_touserdata(L, -1);
- theme->register_html_signal_connection(*live_input, *capture);
+ theme->register_html_signal_connection(chain, *live_input, *capture);
- chain.chain = (EffectChain *)luaL_testudata(L, -2, "EffectChain");
- if (chain.chain == nullptr) {
+ EffectChain *effect_chain = (EffectChain *)luaL_testudata(L, -2, "EffectChain");
+ if (effect_chain == nullptr) {
fprintf(stderr, "get_chain() for chain number %d did not return an EffectChain\n",
num);
exit(1);
}
fprintf(stderr, "get_chain() for chain number %d did not return an EffectChain\n",
num);
exit(1);
}
+ chain.chain = effect_chain;
if (!lua_isfunction(L, -1)) {
fprintf(stderr, "Argument #-1 should be a function\n");
exit(1);
if (!lua_isfunction(L, -1)) {
fprintf(stderr, "Argument #-1 should be a function\n");
exit(1);
lua_pop(L, 2);
assert(lua_gettop(L) == 0);
lua_pop(L, 2);
assert(lua_gettop(L) == 0);
- chain.setup_chain = [this, funcref, input_state]{
+ chain.setup_chain = [this, funcref, input_state, effect_chain]{
unique_lock<mutex> lock(m);
assert(this->input_state == nullptr);
unique_lock<mutex> lock(m);
assert(this->input_state == nullptr);
if (lua_pcall(L, 0, 0, 0) != 0) {
fprintf(stderr, "error running chain setup callback: %s\n", lua_tostring(L, -1));
exit(1);
if (lua_pcall(L, 0, 0, 0) != 0) {
fprintf(stderr, "error running chain setup callback: %s\n", lua_tostring(L, -1));
exit(1);
assert(lua_gettop(L) == 0);
assert(lua_gettop(L) == 0);
+ // The theme can't (or at least shouldn't!) call connect_signal() on
+ // each FFmpeg or CEF input, so we'll do it here.
+ if (video_signal_connections.count(effect_chain)) {
+ for (const VideoSignalConnection &conn : video_signal_connections[effect_chain]) {
+ conn.wrapper->connect_signal_raw(conn.source->get_card_index(), input_state);
+ }
+ }
+#ifdef HAVE_CEF
+ if (html_signal_connections.count(effect_chain)) {
+ for (const CEFSignalConnection &conn : html_signal_connections[effect_chain]) {
+ conn.wrapper->connect_signal_raw(conn.source->get_card_index(), input_state);
+ }
+ }
+#endif
+
this->input_state = nullptr;
};
this->input_state = nullptr;
};
#include <map>
#include <mutex>
#include <string>
#include <map>
#include <mutex>
#include <string>
+#include <unordered_map>
#include <vector>
#include "bmusb/bmusb.h"
#include <vector>
#include "bmusb/bmusb.h"
- void register_video_signal_connection(LiveInputWrapper *live_input, FFmpegCapture *capture)
+ void register_video_signal_connection(movit::EffectChain *chain, LiveInputWrapper *live_input, FFmpegCapture *capture)
- video_signal_connections.emplace_back(live_input, capture);
- }
-
- std::vector<std::pair<LiveInputWrapper *, FFmpegCapture *>> get_video_signal_connections() const
- {
- return video_signal_connections;
+ video_signal_connections[chain].emplace_back(VideoSignalConnection { live_input, capture });
- void register_html_signal_connection(LiveInputWrapper *live_input, CEFCapture *capture)
- {
- html_signal_connections.emplace_back(live_input, capture);
- }
-
- std::vector<std::pair<LiveInputWrapper *, CEFCapture *>> get_html_signal_connections() const
+ void register_html_signal_connection(movit::EffectChain *chain, LiveInputWrapper *live_input, CEFCapture *capture)
- return html_signal_connections;
+ html_signal_connections[chain].emplace_back(CEFSignalConnection { live_input, capture });
std::map<int, int> signal_to_card_mapping; // Protected by <map_m>.
std::vector<FFmpegCapture *> video_inputs;
std::map<int, int> signal_to_card_mapping; // Protected by <map_m>.
std::vector<FFmpegCapture *> video_inputs;
- std::vector<std::pair<LiveInputWrapper *, FFmpegCapture *>> video_signal_connections;
+ struct VideoSignalConnection {
+ LiveInputWrapper *wrapper;
+ FFmpegCapture *source;
+ };
+ std::unordered_map<movit::EffectChain *, std::vector<VideoSignalConnection>>
+ video_signal_connections;
#ifdef HAVE_CEF
std::vector<CEFCapture *> html_inputs;
#ifdef HAVE_CEF
std::vector<CEFCapture *> html_inputs;
- std::vector<std::pair<LiveInputWrapper *, CEFCapture *>> html_signal_connections;
+ struct CEFSignalConnection {
+ LiveInputWrapper *wrapper;
+ CEFCapture *source;
+ };
+ std::unordered_map<movit::EffectChain *, std::vector<CEFSignalConnection>>
+ html_signal_connections;
#endif
std::vector<MenuEntry> theme_menu;
#endif
std::vector<MenuEntry> theme_menu;