X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bmusb.h;h=941c57c27d358ba22f28cb97268f71c475178f9c;hb=ec5eaa5e319e91f89db15dcbccdf64a056f710ae;hp=bf1f51fb60eb65b77a40d26da003787b88414ded;hpb=76a878cbab84d8c3c2859b28a2363085d6a2fcb1;p=bmusb diff --git a/bmusb.h b/bmusb.h index bf1f51f..941c57c 100644 --- a/bmusb.h +++ b/bmusb.h @@ -1,6 +1,7 @@ #ifndef _BMUSB_H #define _BMUSB_H +#include #include #include #include @@ -13,8 +14,7 @@ #include #include -struct libusb_device_handle; -struct libusb_transfer; +class BMUSBCapture; // An interface for frame allocators; if you do not specify one // (using set_video_frame_allocator), a default one that pre-allocates @@ -111,6 +111,9 @@ 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() {} @@ -150,13 +153,17 @@ class CaptureInterface { 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) - : card_index(card_index) + BMUSBCapture(int card_index, libusb_device *dev = nullptr) + : card_index(card_index), dev(dev) { } @@ -223,11 +230,34 @@ class BMUSBCapture : public CaptureInterface { 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; @@ -243,6 +273,7 @@ class BMUSBCapture : public CaptureInterface { 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(); @@ -261,6 +292,8 @@ class BMUSBCapture : public CaptureInterface { 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; @@ -273,13 +306,20 @@ class BMUSBCapture : public CaptureInterface { static constexpr int NUM_BMUSB_REGISTERS = 60; uint8_t register_file[NUM_BMUSB_REGISTERS]; - int card_index; + // 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; }; // Get details for the given video format; returns false if detection was incomplete.