]> git.sesse.net Git - nageru/blobdiff - fake_capture.cpp
Move FakeCapture into bmusb, and make it a little more generic.
[nageru] / fake_capture.cpp
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