]> git.sesse.net Git - nageru/blobdiff - mixer.cpp
Let the theme distinguish between fake and real inputs (ie., if there is an actual...
[nageru] / mixer.cpp
index b76b6745ed2cc61a1f1d2e05358f682c70acc4d8..ce3ceb4bb5b8e58158eb468f5ea16e77ce40823b 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
 #include <utility>
 #include <vector>
 #include <arpa/inet.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include "bmusb/bmusb.h"
 #include "context.h"
 #include "decklink_capture.h"
 #include "defs.h"
+#include "fake_capture.h"
 #include "flags.h"
 #include "video_encoder.h"
 #include "pbo_frame_allocator.h"
@@ -45,6 +48,7 @@ using namespace std;
 using namespace std::placeholders;
 
 Mixer *global_mixer = nullptr;
+bool uses_mlock = false;
 
 namespace {
 
@@ -163,32 +167,48 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards)
        // Start listening for clients only once VideoEncoder has written its header, if any.
        httpd.start(9095);
 
-       // First try initializing the PCI devices, then USB, until we have the desired number of cards.
+       // First try initializing the fake devices, then PCI devices, then USB,
+       // until we have the desired number of cards.
        unsigned num_pci_devices = 0, num_usb_devices = 0;
        unsigned card_index = 0;
 
-       IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance();
-       if (decklink_iterator != nullptr) {
-               for ( ; card_index < num_cards; ++card_index) {
-                       IDeckLink *decklink;
-                       if (decklink_iterator->Next(&decklink) != S_OK) {
-                               break;
-                       }
+       assert(global_flags.num_fake_cards >= 0);  // Enforced in flags.cpp.
+       unsigned num_fake_cards = global_flags.num_fake_cards;
+
+       assert(num_fake_cards <= num_cards);  // Enforced in flags.cpp.
+       for ( ; card_index < num_fake_cards; ++card_index) {
+               configure_card(card_index, format, new FakeCapture(card_index));
+       }
 
-                       configure_card(card_index, format, new DeckLinkCapture(decklink, card_index));
-                       ++num_pci_devices;
+       if (global_flags.num_fake_cards > 0) {
+               fprintf(stderr, "Initialized %d fake cards.\n", global_flags.num_fake_cards);
+       }
+
+       if (card_index < num_cards) {
+               IDeckLinkIterator *decklink_iterator = CreateDeckLinkIteratorInstance();
+               if (decklink_iterator != nullptr) {
+                       for ( ; card_index < num_cards; ++card_index) {
+                               IDeckLink *decklink;
+                               if (decklink_iterator->Next(&decklink) != S_OK) {
+                                       break;
+                               }
+
+                               configure_card(card_index, format, new DeckLinkCapture(decklink, card_index - num_fake_cards));
+                               ++num_pci_devices;
+                       }
+                       decklink_iterator->Release();
+                       fprintf(stderr, "Found %d DeckLink PCI card(s).\n", num_pci_devices);
+               } else {
+                       fprintf(stderr, "DeckLink drivers not found. Probing for USB cards only.\n");
                }
-               decklink_iterator->Release();
-               fprintf(stderr, "Found %d DeckLink PCI card(s).\n", num_pci_devices);
-       } else {
-               fprintf(stderr, "DeckLink drivers not found. Probing for USB cards only.\n");
        }
        for ( ; card_index < num_cards; ++card_index) {
-               configure_card(card_index, format, new BMUSBCapture(card_index - num_pci_devices));
+               configure_card(card_index, format, new BMUSBCapture(card_index - num_pci_devices - num_fake_cards));
                ++num_usb_devices;
        }
 
        if (num_usb_devices > 0) {
+               has_bmusb_thread = true;
                BMUSBCapture::start_bm_thread();
        }
 
@@ -267,7 +287,9 @@ Mixer::~Mixer()
 {
        resource_pool->release_glsl_program(cbcr_program_num);
        glDeleteBuffers(1, &cbcr_vbo);
-       BMUSBCapture::stop_bm_thread();
+       if (has_bmusb_thread) {
+               BMUSBCapture::stop_bm_thread();
+       }
 
        for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
                {
@@ -484,6 +506,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode,
        }
        userdata->last_interlaced = video_format.interlaced;
        userdata->last_has_signal = video_format.has_signal;
+       userdata->last_is_connected = video_format.is_connected;
        userdata->last_frame_rate_nom = video_format.frame_rate_nom;
        userdata->last_frame_rate_den = video_format.frame_rate_den;
        RefCountedFrame frame(video_frame);
@@ -662,12 +685,50 @@ void Mixer::thread_func()
                double elapsed = now.tv_sec - start.tv_sec +
                        1e-9 * (now.tv_nsec - start.tv_nsec);
                if (frame % 100 == 0) {
-                       printf("%d frames (%d dropped) in %.3f seconds = %.1f fps (%.1f ms/frame)\n",
+               // check our memory usage, to see if we are close to our mlockall()
+               // limit (if at all set).
+               rusage used;
+               if (getrusage(RUSAGE_SELF, &used) == -1) {
+                       perror("getrusage(RUSAGE_SELF)");
+                       assert(false);
+               }
+
+               rlimit limit;
+               if (getrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
+                       perror("getrlimit(RLIMIT_MEMLOCK)");
+                       assert(false);
+               }
+
+                       printf("%d frames (%d dropped) in %.3f seconds = %.1f fps (%.1f ms/frame)",
                                frame, stats_dropped_frames, elapsed, frame / elapsed,
                                1e3 * elapsed / frame);
                //      chain->print_phase_timing();
+
+                       if (uses_mlock) {
+                               // Check our memory usage, to see if we are close to our mlockall()
+                               // limit (if at all set).
+                               rusage used;
+                               if (getrusage(RUSAGE_SELF, &used) == -1) {
+                                       perror("getrusage(RUSAGE_SELF)");
+                                       assert(false);
+                               }
+
+                               rlimit limit;
+                               if (getrlimit(RLIMIT_MEMLOCK, &limit) == -1) {
+                                       perror("getrlimit(RLIMIT_MEMLOCK)");
+                                       assert(false);
+                               }
+
+                               printf(", using %ld / %ld MB lockable memory (%.1f%%)",
+                                       long(used.ru_maxrss / 1024),
+                                       long(limit.rlim_cur / 1048576),
+                                       float(100.0 * (used.ru_maxrss * 1024.0) / limit.rlim_cur));
+                       }
+
+                       printf("\n");
                }
 
+
                if (should_cut.exchange(false)) {  // Test and clear.
                        video_encoder->do_cut(frame);
                }