From fc8fb149109f0c12964d53b0dc2dc0f42ef1fc3a Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 21 Apr 2018 11:29:55 +0200 Subject: [PATCH] Fix a problem where the previews would flicker. 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. --- mixer.cpp | 11 ----------- theme.cpp | 28 ++++++++++++++++++++++------ theme.h | 33 +++++++++++++++++---------------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/mixer.cpp b/mixer.cpp index 0b4a8fe..202617b 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -1350,17 +1350,6 @@ void Mixer::render_one_frame(int64_t duration) 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 &conn : theme->get_video_signal_connections()) { - conn.first->connect_signal_raw(conn.second->get_card_index(), input_state); - } -#ifdef HAVE_CEF - for (const pair &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; diff --git a/theme.cpp b/theme.cpp index 45df66f..0fa4d1d 100644 --- a/theme.cpp +++ b/theme.cpp @@ -297,7 +297,7 @@ int EffectChain_add_video_input(lua_State* L) 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); } return ret; } @@ -320,7 +320,7 @@ int EffectChain_add_html_input(lua_State* L) 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); } return ret; } @@ -1256,12 +1256,13 @@ Theme::Chain Theme::get_chain(unsigned num, float t, unsigned width, unsigned he exit(1); } - 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); } + chain.chain = effect_chain; if (!lua_isfunction(L, -1)) { fprintf(stderr, "Argument #-1 should be a function\n"); exit(1); @@ -1271,7 +1272,7 @@ Theme::Chain Theme::get_chain(unsigned num, float t, unsigned width, unsigned he 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 lock(m); assert(this->input_state == nullptr); @@ -1282,9 +1283,24 @@ Theme::Chain Theme::get_chain(unsigned num, float t, unsigned width, unsigned he 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); + // 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; }; diff --git a/theme.h b/theme.h index d2f6d2c..bbef35e 100644 --- a/theme.h +++ b/theme.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "bmusb/bmusb.h" @@ -82,25 +83,15 @@ public: } #endif - 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> get_video_signal_connections() const - { - return video_signal_connections; + video_signal_connections[chain].emplace_back(VideoSignalConnection { live_input, capture }); } #ifdef HAVE_CEF - void register_html_signal_connection(LiveInputWrapper *live_input, CEFCapture *capture) - { - html_signal_connections.emplace_back(live_input, capture); - } - - std::vector> 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 }); } #endif @@ -136,10 +127,20 @@ private: std::map signal_to_card_mapping; // Protected by . std::vector video_inputs; - std::vector> video_signal_connections; + struct VideoSignalConnection { + LiveInputWrapper *wrapper; + FFmpegCapture *source; + }; + std::unordered_map> + video_signal_connections; #ifdef HAVE_CEF std::vector html_inputs; - std::vector> html_signal_connections; + struct CEFSignalConnection { + LiveInputWrapper *wrapper; + CEFCapture *source; + }; + std::unordered_map> + html_signal_connections; #endif std::vector theme_menu; -- 2.39.2