From 8e0a25a2663844905f3daf8fcf9bf9ec995d1074 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Tue, 26 Jul 2016 17:42:51 +0200 Subject: [PATCH] Move include files to bmusb/. --- Makefile | 2 +- bmusb.cpp | 2 +- bmusb.h | 333 ----------------------------------------------- fake_capture.cpp | 4 +- fake_capture.h | 104 --------------- main.cpp | 2 +- 6 files changed, 5 insertions(+), 442 deletions(-) delete mode 100644 bmusb.h delete mode 100644 fake_capture.h diff --git a/Makefile b/Makefile index a147176..46da303 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CXXFLAGS := -std=gnu++14 -O2 -Wall -g $(shell pkg-config libusb-1.0 --cflags) -pthread +CXXFLAGS := -std=gnu++14 -O2 -Wall -I. -g $(shell pkg-config libusb-1.0 --cflags) -pthread LDFLAGS := $(shell pkg-config libusb-1.0 --libs) -pthread AR := ar RANLIB := ranlib diff --git a/bmusb.cpp b/bmusb.cpp index c4758f5..ec3eac2 100644 --- a/bmusb.cpp +++ b/bmusb.cpp @@ -21,7 +21,7 @@ #if HAS_MULTIVERSIONING #include #endif -#include "bmusb.h" +#include "bmusb/bmusb.h" #include #include diff --git a/bmusb.h b/bmusb.h deleted file mode 100644 index 506685d..0000000 --- a/bmusb.h +++ /dev/null @@ -1,333 +0,0 @@ -#ifndef _BMUSB_H -#define _BMUSB_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace bmusb { - -class BMUSBCapture; - -// An interface for frame allocators; if you do not specify one -// (using set_video_frame_allocator), a default one that pre-allocates -// a freelist of eight frames using new[] will be used. Specifying -// your own can be useful if you have special demands for where you want the -// frame to end up and don't want to spend the extra copy to get it there, for -// instance GPU memory. -class FrameAllocator { - public: - struct Frame { - uint8_t *data = nullptr; - uint8_t *data2 = nullptr; // Only if interleaved == true. - size_t len = 0; // Number of bytes we actually have. - size_t size = 0; // Number of bytes we have room for. - size_t overflow = 0; - void *userdata = nullptr; - FrameAllocator *owner = nullptr; - - // If set to true, every other byte will go to data and to data2. - // If so, and are still about the number of total bytes - // so if size == 1024, there's 512 bytes in data and 512 in data2. - bool interleaved = false; - }; - - virtual ~FrameAllocator(); - - // Request a video frame. Note that this is called from the - // USB thread, which runs with realtime priority and is - // very sensitive to delays. Thus, you should not do anything - // here that might sleep, including calling malloc(). - // (Taking a mutex is borderline.) - // - // The Frame object will be given to the frame callback, - // which is responsible for releasing the video frame back - // once it is usable for new frames (ie., it will no longer - // be read from). You can use the "userdata" pointer for - // whatever you want to identify this frame if you need to. - // - // Returning a Frame with data==nullptr is allowed; - // if so, the frame in progress will be dropped. - virtual Frame alloc_frame() = 0; - - virtual void release_frame(Frame frame) = 0; -}; - -// Audio is more important than video, and also much cheaper. -// By having many more audio frames available, hopefully if something -// starts to drop, we'll have CPU load go down (from not having to -// process as much video) before we have to drop audio. -#define NUM_QUEUED_VIDEO_FRAMES 16 -#define NUM_QUEUED_AUDIO_FRAMES 64 - -class MallocFrameAllocator : public FrameAllocator { -public: - MallocFrameAllocator(size_t frame_size, size_t num_queued_frames); - Frame alloc_frame() override; - void release_frame(Frame frame) override; - -private: - size_t frame_size; - - std::mutex freelist_mutex; - std::stack> freelist; // All of size . -}; - -// Represents an input mode you can tune a card to. -struct VideoMode { - std::string name; - bool autodetect = false; // If true, all the remaining fields are irrelevant. - unsigned width = 0, height = 0; - unsigned frame_rate_num = 0, frame_rate_den = 0; - bool interlaced = false; -}; - -// Represents the format of an actual frame coming in. -// Note: Frame rate is _frame_ rate, not field rate. So 1080i60 gets 30/1, _not_ 60/1. -// "second_field_start" is only valid for interlaced modes; it signifies -// how many lines from the very top of the frame there are before the second field -// starts (so it will always be >= height/2 + extra_lines_top). -struct VideoFormat { - uint16_t id = 0; // For debugging/logging only. - unsigned width = 0, height = 0, second_field_start = 0; - unsigned extra_lines_top = 0, extra_lines_bottom = 0; - unsigned frame_rate_nom = 0, frame_rate_den = 0; - bool interlaced = false; - bool has_signal = false; - bool is_connected = true; // If false, then has_signal makes no sense. -}; - -struct AudioFormat { - uint16_t id = 0; // For debugging/logging only. - unsigned bits_per_sample = 0; - unsigned num_channels = 0; -}; - -typedef std::function - frame_callback_t; - -typedef std::function card_connected_callback_t; -typedef std::function card_disconnected_callback_t; - -class CaptureInterface { - public: - virtual ~CaptureInterface() {} - - virtual std::map get_available_video_modes() const = 0; - virtual uint32_t get_current_video_mode() const = 0; - virtual void set_video_mode(uint32_t video_mode_id) = 0; - - virtual std::map get_available_video_inputs() const = 0; - virtual void set_video_input(uint32_t video_input_id) = 0; - virtual uint32_t get_current_video_input() const = 0; - - virtual std::map get_available_audio_inputs() const = 0; - virtual void set_audio_input(uint32_t audio_input_id) = 0; - virtual uint32_t get_current_audio_input() const = 0; - - // Does not take ownership. - virtual void set_video_frame_allocator(FrameAllocator *allocator) = 0; - - virtual FrameAllocator *get_video_frame_allocator() = 0; - - // Does not take ownership. - virtual void set_audio_frame_allocator(FrameAllocator *allocator) = 0; - - virtual FrameAllocator *get_audio_frame_allocator() = 0; - - virtual void set_frame_callback(frame_callback_t callback) = 0; - - // Needs to be run before configure_card(). - virtual void set_dequeue_thread_callbacks(std::function init, std::function cleanup) = 0; - - // Only valid after configure_card(). - virtual std::string get_description() const = 0; - - virtual void configure_card() = 0; - - virtual void start_bm_capture() = 0; - - virtual void stop_dequeue_thread() = 0; - - // If a card is disconnected, it cannot come back; you should call stop_dequeue_thread() - // and delete it. - virtual bool get_disconnected() const = 0; -}; - -// The actual capturing class, representing capture from a single card. -class BMUSBCapture : public CaptureInterface { - public: - BMUSBCapture(int card_index, libusb_device *dev = nullptr) - : card_index(card_index), dev(dev) - { - } - - ~BMUSBCapture() {} - - std::map get_available_video_modes() const override; - uint32_t get_current_video_mode() const override; - void set_video_mode(uint32_t video_mode_id) override; - - virtual std::map get_available_video_inputs() const override; - virtual void set_video_input(uint32_t video_input_id) override; - virtual uint32_t get_current_video_input() const override { return current_video_input; } - - virtual std::map get_available_audio_inputs() const override; - virtual void set_audio_input(uint32_t audio_input_id) override; - virtual uint32_t get_current_audio_input() const override { return current_audio_input; } - - // Does not take ownership. - 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; - } - - // Needs to be run before configure_card(). - void set_dequeue_thread_callbacks(std::function init, std::function cleanup) override - { - dequeue_init_callback = init; - dequeue_cleanup_callback = cleanup; - has_dequeue_callbacks = true; - } - - // Only valid after configure_card(). - 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 disconnected; } - - // TODO: It's rather messy to have these outside the interface. - static void start_bm_thread(); - static void stop_bm_thread(); - - // Hotplug event (for devices being inserted between start_bm_thread() - // and stop_bm_thread()); entirely optional, but must be set before - // start_bm_capture(). Note that your callback should do as little work - // as possible, since the callback comes from the main USB handling - // thread, which is very time-sensitive. - // - // The callback function transfers ownership. If you don't want to hold - // on to the device given to you in the callback, you need to call - // libusb_unref_device(). - static void set_card_connected_callback(card_connected_callback_t callback) - { - card_connected_callback = callback; - } - - // Similar to set_card_connected_callback(), with the same caveats. - // (Note that this is set per-card and not global, as it is logically - // connected to an existing BMUSBCapture object.) - void set_card_disconnected_callback(card_disconnected_callback_t callback) - { - card_disconnected_callback = callback; - } - - private: - struct QueuedFrame { - uint16_t timecode; - uint16_t format; - FrameAllocator::Frame frame; - }; - - void start_new_audio_block(const uint8_t *start); - void start_new_frame(const uint8_t *start); - - void queue_frame(uint16_t format, uint16_t timecode, FrameAllocator::Frame frame, std::deque *q); - void dequeue_thread_func(); - - static void usb_thread_func(); - static void cb_xfr(struct libusb_transfer *xfr); - static int cb_hotplug(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data); - - void update_capture_mode(); - - std::string description; - - FrameAllocator::Frame current_video_frame; - FrameAllocator::Frame current_audio_frame; - - std::mutex queue_lock; - std::condition_variable queues_not_empty; - std::deque pending_video_frames; - std::deque pending_audio_frames; - - FrameAllocator *video_frame_allocator = nullptr; - FrameAllocator *audio_frame_allocator = nullptr; - std::unique_ptr owned_video_frame_allocator; - std::unique_ptr owned_audio_frame_allocator; - frame_callback_t frame_callback = nullptr; - static card_connected_callback_t card_connected_callback; - card_disconnected_callback_t card_disconnected_callback = nullptr; - - std::thread dequeue_thread; - std::atomic dequeue_thread_should_quit; - bool has_dequeue_callbacks = false; - std::function dequeue_init_callback = nullptr; - std::function dequeue_cleanup_callback = nullptr; - - int current_register = 0; - - static constexpr int NUM_BMUSB_REGISTERS = 60; - uint8_t register_file[NUM_BMUSB_REGISTERS]; - - // If is nullptr, will choose device number from the list - // of available devices on the system. is not used after configure_card() - // (it will be unref-ed). - int card_index = -1; - libusb_device *dev = nullptr; - - std::vector iso_xfrs; - int assumed_frame_width = 1280; - - libusb_device_handle *devh = nullptr; - uint32_t current_video_input = 0x00000000; // HDMI/SDI. - uint32_t current_audio_input = 0x00000000; // Embedded. - - bool disconnected = false; -}; - -} // namespace bmusb - -#endif diff --git a/fake_capture.cpp b/fake_capture.cpp index 9cb2afe..1410ef4 100644 --- a/fake_capture.cpp +++ b/fake_capture.cpp @@ -1,7 +1,7 @@ // 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 "bmusb/fake_capture.h" #include #include @@ -15,7 +15,7 @@ #endif #include -#include "bmusb.h" +#include "bmusb/bmusb.h" #define FRAME_SIZE (8 << 20) // 8 MB. diff --git a/fake_capture.h b/fake_capture.h deleted file mode 100644 index 93f1470..0000000 --- a/fake_capture.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef _FAKE_CAPTURE_H -#define _FAKE_CAPTURE_H 1 - -#include -#include -#include - -#include "bmusb.h" - -namespace bmusb { - -class FakeCapture : public CaptureInterface -{ -public: - FakeCapture(unsigned width, unsigned height, unsigned fps, unsigned audio_frequency, 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 init, std::function 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 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 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 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(); - - unsigned width, height, fps, audio_frequency; - uint8_t y, cb, cr; - - bool has_dequeue_callbacks = false; - std::function dequeue_init_callback = nullptr; - std::function dequeue_cleanup_callback = nullptr; - - FrameAllocator *video_frame_allocator = nullptr; - FrameAllocator *audio_frame_allocator = nullptr; - std::unique_ptr owned_video_frame_allocator; - std::unique_ptr owned_audio_frame_allocator; - frame_callback_t frame_callback = nullptr; - - std::string description; - - std::atomic producer_thread_should_quit{false}; - std::thread producer_thread; -}; - -} // namespace bmusb - -#endif // !defined(_FAKE_CAPTURE_H) diff --git a/main.cpp b/main.cpp index f1844cd..a50363a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,6 @@ #include #include -#include "bmusb.h" +#include "bmusb/bmusb.h" using namespace std; using namespace bmusb; -- 2.39.2