]> git.sesse.net Git - nageru/commitdiff
When reconnecting an SRT input, try to use the same slot as last time.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 15 May 2020 17:41:46 +0000 (19:41 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 15 May 2020 17:54:46 +0000 (19:54 +0200)
nageru/mixer.cpp
nageru/mixer.h

index 212041bd1b0f5c69ecab7e6116e5e1844015ad8e..a773d6c60db99cb59530301f95f21b0f6f299120 100644 (file)
@@ -559,6 +559,9 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, CardT
        }
        card->capture.reset(capture);
        card->is_fake_capture = (card_type == CardType::FAKE_CAPTURE);
+       if (card->is_fake_capture) {
+               card->fake_capture_counter = fake_capture_counter++;
+       }
        card->is_cef_capture = (card_type == CardType::CEF_INPUT);
        card->may_have_dropped_last_frame = false;
        card->type = card_type;
@@ -1428,22 +1431,35 @@ void Mixer::handle_hotplugged_cards()
 #ifdef HAVE_SRT
        // Same, for SRT inputs.
        // TODO: On disconnect and reconnect, we might want to use the stream ID
-       // to find the slot it used to go into?
        for (SRTSOCKET sock : hotplugged_srt_cards_copy) {
-               // Look for a fake capture card where we can stick this in.
-               int free_card_index = -1;
-               for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
-                       if (cards[card_index].is_fake_capture) {
-                               free_card_index = card_index;
-                               break;
-                       }
-               }
-
                char name[256];
                int namelen = sizeof(name);
                srt_getsockopt(sock, /*ignored=*/0, SRTO_STREAMID, name, &namelen);
                string stream_id(name, namelen);
 
+               // Look for a fake capture card where we can stick this in.
+               // Prioritize ones that previously held SRT streams with the
+               // same stream ID, if any exist -- and it multiple exist,
+               // take the one that disconnected the last.
+               int first_free_card_index = -1, last_matching_free_card_index = -1;
+               for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
+                       CaptureCard *card = &cards[card_index];
+                       if (!card->is_fake_capture) {
+                               continue;
+                       }
+                       if (first_free_card_index == -1) {
+                               first_free_card_index = card_index;
+                       }
+                       if (card->last_srt_stream_id == stream_id &&
+                           (last_matching_free_card_index == -1 ||
+                            card->fake_capture_counter >
+                               cards[last_matching_free_card_index].fake_capture_counter)) {
+                               last_matching_free_card_index = card_index;
+                       }
+               }
+
+               const int free_card_index = (last_matching_free_card_index != -1)
+                       ? last_matching_free_card_index : first_free_card_index;
                if (free_card_index == -1) {
                        if (stream_id.empty()) {
                                stream_id = "no name";
@@ -1461,6 +1477,7 @@ void Mixer::handle_hotplugged_cards()
                        FFmpegCapture *capture = new FFmpegCapture(sock, stream_id);
                        capture->set_card_index(free_card_index);
                        configure_card(free_card_index, capture, CardType::FFMPEG_INPUT, /*output=*/nullptr, /*override_card_as_live=*/true);
+                       card->last_srt_stream_id = stream_id;
                        card->queue_length_policy.reset(free_card_index);
                        capture->set_card_disconnected_callback(bind(&Mixer::bm_hotplug_remove, this, free_card_index));
                        capture->start_bm_capture();
index ff8a197bccdd61c6af9de3598f6239e6645553d5..235dd8da3fba1bf1b9c4325f89c7bf0a6c11b130 100644 (file)
@@ -510,11 +510,19 @@ private:
        // frame rate is integer, will always stay zero.
        unsigned fractional_samples = 0;
 
+       // Monotonic counter that lets us know which slot was last turned into
+       // a fake capture. Used for SRT re-plugging.
+       unsigned fake_capture_counter = 0;
+
        mutable std::mutex card_mutex;
        bool has_bmusb_thread = false;
        struct CaptureCard {
                std::unique_ptr<bmusb::CaptureInterface> capture;
                bool is_fake_capture;
+               // If is_fake_capture is true, contains a monotonic timer value for when
+               // it was last changed. Otherwise undefined. Used for SRT re-plugging.
+               int fake_capture_counter;
+               std::string last_srt_stream_id = "<default, matches nothing>";  // Used for SRT re-plugging.
                CardType type;
                std::unique_ptr<DeckLinkOutput> output;