]> git.sesse.net Git - nageru/commitdiff
Fix a problem where the previews would flicker.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 21 Apr 2018 09:29:55 +0000 (11:29 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 21 Apr 2018 09:29:55 +0000 (11:29 +0200)
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
theme.cpp
theme.h

index 0b4a8fe5a823b6ca9651127dca35a8ea9a1d3c41..202617b9b718aae8b05ffb3872bafce980cc5b2a 100644 (file)
--- 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<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;
index 45df66f85462e7ecdb853c78065de9d72bb3ae2e..0fa4d1d5ea3702936ef3aa44cdbc60fe50b01689 100644 (file)
--- 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<mutex> 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 d2f6d2c586a396199af736e6898b6ea0526a2641..bbef35ef350d1513afc92aa8216836b13b36b937 100644 (file)
--- a/theme.h
+++ b/theme.h
@@ -9,6 +9,7 @@
 #include <map>
 #include <mutex>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #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<std::pair<LiveInputWrapper *, FFmpegCapture *>> 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<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 });
        }
 #endif
 
@@ -136,10 +127,20 @@ private:
        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;
-       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;