]> git.sesse.net Git - nageru/commitdiff
Move FakeCapture into bmusb, and make it a little more generic.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 25 Jul 2016 12:17:45 +0000 (14:17 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 25 Jul 2016 12:18:23 +0000 (14:18 +0200)
Makefile
bmusb
defs.h
fake_capture.cpp [deleted file]
fake_capture.h [deleted file]
mixer.cpp

index fb171a75fb755a002f64b90337283ff083f80fae..a88b7f653318c042eaf4af1fa42b9a0bffb10cd1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ OBJS=glwidget.o main.o mainwindow.o vumeter.o lrameter.o vu_common.o correlation
 OBJS += glwidget.moc.o mainwindow.moc.o vumeter.moc.o lrameter.moc.o correlation_meter.moc.o aboutdialog.moc.o
 
 # Mixer objects
-OBJS += mixer.o bmusb/bmusb.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampling_queue.o httpd.o ebu_r128_proc.o flags.o image_input.o stereocompressor.o filter.o alsa_output.o correlation_measurer.o fake_capture.o
+OBJS += mixer.o bmusb/bmusb.o bmusb/fake_capture.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampling_queue.o httpd.o ebu_r128_proc.o flags.o image_input.o stereocompressor.o filter.o alsa_output.o correlation_measurer.o
 
 # Streaming and encoding objects
 OBJS += quicksync_encoder.o x264_encoder.o x264_speed_control.o video_encoder.o metacube2.o mux.o audio_encoder.o
diff --git a/bmusb b/bmusb
index c66728fa32fc79abd5c4fb9188750cccf9039dee..96c41434726ef4b603f58cc3cafbb1630bea269e 160000 (submodule)
--- a/bmusb
+++ b/bmusb
@@ -1 +1 @@
-Subproject commit c66728fa32fc79abd5c4fb9188750cccf9039dee
+Subproject commit 96c41434726ef4b603f58cc3cafbb1630bea269e
diff --git a/defs.h b/defs.h
index 05a38996747e05e3a4df6dfc05aa1ca31e03dee7..498ade913215c23d61356135ca585deb16c3cd75 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -5,6 +5,7 @@
 #define MAX_FPS 60
 #define WIDTH 1280
 #define HEIGHT 720
+#define FAKE_FPS 25  // Must be an integer.
 #define MAX_CARDS 16
 
 // For deinterlacing. See also comments on InputState.
diff --git a/fake_capture.cpp b/fake_capture.cpp
deleted file mode 100644 (file)
index 7d23d8c..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-// A fake capture device that sends single-color frames at a given rate.
-// Mostly useful for testing themes without actually hooking up capture devices.
-
-#include "fake_capture.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <unistd.h>
-#if __SSE2__
-#include <immintrin.h>
-#endif
-#include <cstddef>
-
-#include "bmusb/bmusb.h"
-#include "defs.h"
-
-#define FRAME_SIZE (8 << 20)  // 8 MB.
-#define FAKE_FPS 25  // Must be an integer.
-
-// Pure-color inputs: Red, green, blue, white.
-#define NUM_COLORS 4
-constexpr uint8_t ys[NUM_COLORS] = { 81, 145, 41, 235 };
-constexpr uint8_t cbs[NUM_COLORS] = { 90, 54, 240, 128 };
-constexpr uint8_t crs[NUM_COLORS] = { 240, 34, 110, 128 };
-
-using namespace std;
-
-namespace bmusb {
-namespace {
-
-void memset2(uint8_t *s, const uint8_t c[2], size_t n)
-{
-       size_t i = 0;
-#if __SSE2__
-       const uint8_t c_expanded[16] = {
-               c[0], c[1], c[0], c[1], c[0], c[1], c[0], c[1],
-               c[0], c[1], c[0], c[1], c[0], c[1], c[0], c[1]
-       };
-       __m128i cc = *(__m128i *)c_expanded;
-       __m128i *out = (__m128i *)s;
-
-       for ( ; i < (n & ~15); i += 16) {
-               _mm_storeu_si128(out++, cc);
-               _mm_storeu_si128(out++, cc);
-       }
-
-       s = (uint8_t *)out;
-#endif
-       for ( ; i < n; ++i) {
-               *s++ = c[0];
-               *s++ = c[1];
-       }
-}
-
-void memset4(uint8_t *s, const uint8_t c[4], size_t n)
-{
-       size_t i = 0;
-#if __SSE2__
-       const uint8_t c_expanded[16] = {
-               c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3],
-               c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]
-       };
-       __m128i cc = *(__m128i *)c_expanded;
-       __m128i *out = (__m128i *)s;
-
-       for ( ; i < (n & ~7); i += 8) {
-               _mm_storeu_si128(out++, cc);
-               _mm_storeu_si128(out++, cc);
-       }
-
-       s = (uint8_t *)out;
-#endif
-       for ( ; i < n; ++i) {
-               *s++ = c[0];
-               *s++ = c[1];
-               *s++ = c[2];
-               *s++ = c[3];
-       }
-}
-
-}  // namespace
-
-FakeCapture::FakeCapture(int card_index)
-{
-       char buf[256];
-       snprintf(buf, sizeof(buf), "Fake card %d", card_index + 1);
-       description = buf;
-
-       y = ys[card_index % NUM_COLORS];
-       cb = cbs[card_index % NUM_COLORS];
-       cr = crs[card_index % NUM_COLORS];
-}
-
-FakeCapture::~FakeCapture()
-{
-       if (has_dequeue_callbacks) {
-               dequeue_cleanup_callback();
-       }
-}
-
-void FakeCapture::configure_card()
-{
-       if (video_frame_allocator == nullptr) {
-               owned_video_frame_allocator.reset(new MallocFrameAllocator(FRAME_SIZE, NUM_QUEUED_VIDEO_FRAMES));
-               set_video_frame_allocator(owned_video_frame_allocator.get());
-       }
-       if (audio_frame_allocator == nullptr) {
-               owned_audio_frame_allocator.reset(new MallocFrameAllocator(65536, NUM_QUEUED_AUDIO_FRAMES));
-               set_audio_frame_allocator(owned_audio_frame_allocator.get());
-       }
-}
-
-void FakeCapture::start_bm_capture()
-{
-       producer_thread_should_quit = false;
-       producer_thread = thread(&FakeCapture::producer_thread_func, this);
-}
-
-void FakeCapture::stop_dequeue_thread()
-{
-       producer_thread_should_quit = true;
-       producer_thread.join();
-}
-       
-std::map<uint32_t, VideoMode> FakeCapture::get_available_video_modes() const
-{
-       VideoMode mode;
-
-       char buf[256];
-       snprintf(buf, sizeof(buf), "%dx%d", WIDTH, HEIGHT);
-       mode.name = buf;
-       
-       mode.autodetect = false;
-       mode.width = WIDTH;
-       mode.height = HEIGHT;
-       mode.frame_rate_num = FAKE_FPS;
-       mode.frame_rate_den = 1;
-       mode.interlaced = false;
-
-       return {{ 0, mode }};
-}
-
-std::map<uint32_t, std::string> FakeCapture::get_available_video_inputs() const
-{
-       return {{ 0, "Fake video input (single color)" }};
-}
-
-std::map<uint32_t, std::string> FakeCapture::get_available_audio_inputs() const
-{
-       return {{ 0, "Fake audio input (silence)" }};
-}
-
-void FakeCapture::set_video_mode(uint32_t video_mode_id)
-{
-       assert(video_mode_id == 0);
-}
-
-void FakeCapture::set_video_input(uint32_t video_input_id)
-{
-       assert(video_input_id == 0);
-}
-
-void FakeCapture::set_audio_input(uint32_t audio_input_id)
-{
-       assert(audio_input_id == 0);
-}
-
-namespace {
-
-void add_time(double t, timespec *ts)
-{
-       ts->tv_nsec += lrint(t * 1e9);
-       ts->tv_sec += ts->tv_nsec / 1000000000;
-       ts->tv_nsec %= 1000000000;
-}
-
-bool timespec_less_than(const timespec &a, const timespec &b)
-{
-       return make_pair(a.tv_sec, a.tv_nsec) < make_pair(b.tv_sec, b.tv_nsec);
-}
-
-}  // namespace
-
-void FakeCapture::producer_thread_func()
-{
-       uint16_t timecode = 0;
-
-       if (has_dequeue_callbacks) {
-               dequeue_init_callback();
-       }
-
-       timespec next_frame;
-       clock_gettime(CLOCK_MONOTONIC, &next_frame);
-       add_time(1.0 / FAKE_FPS, &next_frame);
-
-       while (!producer_thread_should_quit) {
-               timespec now;
-               clock_gettime(CLOCK_MONOTONIC, &now);
-
-               if (timespec_less_than(now, next_frame)) {
-                       // Wait until the next frame.
-                       if (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
-                                            &next_frame, nullptr) == -1) {
-                               if (errno == EINTR) continue;  // Re-check the flag and then sleep again.
-                               perror("clock_nanosleep");
-                               exit(1);
-                       }
-               } else {
-                       // We've seemingly missed a frame. If we're more than one second behind,
-                       // reset the timer; otherwise, just keep going.
-                       timespec limit = next_frame;
-                       ++limit.tv_sec;
-                       if (!timespec_less_than(now, limit)) {
-                               fprintf(stderr, "More than one second of missed fake frames; resetting clock.\n");
-                               next_frame = now;
-                       }
-               }
-
-               // Figure out when the next frame is to be, then compute the current one.
-               add_time(1.0 / FAKE_FPS, &next_frame);
-
-               VideoFormat video_format;
-               video_format.width = WIDTH;
-               video_format.height = HEIGHT;
-               video_format.frame_rate_nom = FAKE_FPS;
-               video_format.frame_rate_den = 1;
-               video_format.has_signal = true;
-               video_format.is_connected = false;
-
-               FrameAllocator::Frame video_frame = video_frame_allocator->alloc_frame();
-               if (video_frame.data != nullptr) {
-                       assert(video_frame.size >= WIDTH * HEIGHT * 2);
-                       if (video_frame.interleaved) {
-                               uint8_t cbcr[] = { cb, cr };
-                               memset2(video_frame.data, cbcr, WIDTH * HEIGHT / 2);
-                               memset(video_frame.data2, y, WIDTH * HEIGHT);
-                       } else {
-                               uint8_t ycbcr[] = { y, cb, y, cr };
-                               memset4(video_frame.data, ycbcr, WIDTH * HEIGHT / 2);
-                       }
-                       video_frame.len = WIDTH * HEIGHT * 2;
-               }
-
-               AudioFormat audio_format;
-               audio_format.bits_per_sample = 32;
-               audio_format.num_channels = 2;
-
-               FrameAllocator::Frame audio_frame = audio_frame_allocator->alloc_frame();
-               if (audio_frame.data != nullptr) {
-                       assert(audio_frame.size >= 2 * sizeof(uint32_t) * OUTPUT_FREQUENCY / FAKE_FPS);
-                       audio_frame.len = 2 * sizeof(uint32_t) * OUTPUT_FREQUENCY / FAKE_FPS;
-                       memset(audio_frame.data, 0, audio_frame.len);
-               }
-
-               frame_callback(timecode++,
-                              video_frame, 0, video_format,
-                              audio_frame, 0, audio_format);
-       }
-       if (has_dequeue_callbacks) {
-               dequeue_cleanup_callback();
-       }
-}
-
-}  // namespace bmusb
diff --git a/fake_capture.h b/fake_capture.h
deleted file mode 100644 (file)
index 84a8953..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef _FAKE_CAPTURE_H
-#define _FAKE_CAPTURE_H 1
-
-#include <stdint.h>
-#include <functional>
-#include <string>
-
-#include "bmusb/bmusb.h"
-
-namespace bmusb {
-
-class FakeCapture : public CaptureInterface
-{
-public:
-       FakeCapture(int card_index);
-       ~FakeCapture();
-
-       // CaptureInterface.
-       void set_video_frame_allocator(FrameAllocator *allocator) override
-       {
-               video_frame_allocator = allocator;
-               if (owned_video_frame_allocator.get() != allocator) {
-                       owned_video_frame_allocator.reset();
-               }
-       }
-
-       FrameAllocator *get_video_frame_allocator() override
-       {
-               return video_frame_allocator;
-       }
-
-       // Does not take ownership.
-       void set_audio_frame_allocator(FrameAllocator *allocator) override
-       {
-               audio_frame_allocator = allocator;
-               if (owned_audio_frame_allocator.get() != allocator) {
-                       owned_audio_frame_allocator.reset();
-               }
-       }
-
-       FrameAllocator *get_audio_frame_allocator() override
-       {
-               return audio_frame_allocator;
-       }
-
-       void set_frame_callback(frame_callback_t callback) override
-       {
-               frame_callback = callback;
-       }
-
-       void set_dequeue_thread_callbacks(std::function<void()> init, std::function<void()> cleanup) override
-       {
-               dequeue_init_callback = init;
-               dequeue_cleanup_callback = cleanup;
-               has_dequeue_callbacks = true;
-       }
-
-       std::string get_description() const override
-       {
-               return description;
-       }
-
-       void configure_card() override;
-       void start_bm_capture() override;
-       void stop_dequeue_thread() override;
-       bool get_disconnected() const override { return false; }
-
-       std::map<uint32_t, VideoMode> get_available_video_modes() const override;
-       void set_video_mode(uint32_t video_mode_id) override;
-       uint32_t get_current_video_mode() const override { return 0; }
-
-       std::map<uint32_t, std::string> get_available_video_inputs() const override;
-       void set_video_input(uint32_t video_input_id) override;
-       uint32_t get_current_video_input() const override { return 0; }
-
-       std::map<uint32_t, std::string> get_available_audio_inputs() const override;
-       void set_audio_input(uint32_t audio_input_id) override;
-       uint32_t get_current_audio_input() const override { return 0; }
-
-private:
-       void producer_thread_func();
-
-       uint8_t y, cb, cr;
-
-       bool has_dequeue_callbacks = false;
-       std::function<void()> dequeue_init_callback = nullptr;
-       std::function<void()> dequeue_cleanup_callback = nullptr;
-
-       FrameAllocator *video_frame_allocator = nullptr;
-       FrameAllocator *audio_frame_allocator = nullptr;
-       std::unique_ptr<FrameAllocator> owned_video_frame_allocator;
-       std::unique_ptr<FrameAllocator> owned_audio_frame_allocator;
-       frame_callback_t frame_callback = nullptr;
-
-       std::string description;
-
-       std::atomic<bool> producer_thread_should_quit{false};
-       std::thread producer_thread;
-};
-
-}  // namespace bmusb
-
-#endif  // !defined(_FAKE_CAPTURE_H)
index 6bc878074f2fa77e9ef9ef6da6157d54dc202eaa..e087796f188eb9a454db87f696a028feed78444a 100644 (file)
--- a/mixer.cpp
+++ b/mixer.cpp
 #include <sys/resource.h>
 
 #include "bmusb/bmusb.h"
+#include "bmusb/fake_capture.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"
@@ -178,7 +178,7 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards)
 
        assert(num_fake_cards <= num_cards);  // Enforced in flags.cpp.
        for ( ; card_index < num_fake_cards; ++card_index) {
-               configure_card(card_index, new FakeCapture(card_index), /*is_fake_capture=*/true);
+               configure_card(card_index, new FakeCapture(WIDTH, HEIGHT, FAKE_FPS, OUTPUT_FREQUENCY, card_index), /*is_fake_capture=*/true);
        }
 
        if (global_flags.num_fake_cards > 0) {
@@ -824,7 +824,7 @@ void Mixer::handle_hotplugged_cards()
                CaptureCard *card = &cards[card_index];
                if (card->capture->get_disconnected()) {
                        fprintf(stderr, "Card %u went away, replacing with a fake card.\n", card_index);
-                       configure_card(card_index, new FakeCapture(card_index), /*is_fake_capture=*/true);
+                       configure_card(card_index, new FakeCapture(WIDTH, HEIGHT, FAKE_FPS, OUTPUT_FREQUENCY, card_index), /*is_fake_capture=*/true);
                        card->queue_length_policy.reset(card_index);
                        card->capture->start_bm_capture();
                }