X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bmusb.h;h=04d867b009e49cabc4fdcd6cf63a3f3b46b88b1e;hb=bb575c1ac8b1496394732800898c27a3a812f0a9;hp=301350f53be858fac1885f0821920bdbac600e2c;hpb=30929c8ebab480afe338104cbc490016d8dcc932;p=bmusb diff --git a/bmusb.h b/bmusb.h index 301350f..04d867b 100644 --- a/bmusb.h +++ b/bmusb.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,7 @@ class FrameAllocator { 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; @@ -55,16 +57,24 @@ class FrameAllocator { virtual void release_frame(Frame frame) = 0; }; +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; +}; + typedef std::function frame_callback_t; // The actual capturing class, representing capture from a single card. class BMUSBCapture { public: - BMUSBCapture(int vid = 0x1edb, int pid = 0xbd3b) - : vid(vid), pid(pid) + BMUSBCapture(int card_index) + : card_index(card_index) { } @@ -95,8 +105,22 @@ class BMUSBCapture { frame_callback = callback; } + // Needs to be run before configure_card(). + void set_dequeue_thread_callbacks(std::function init, std::function cleanup) + { + dequeue_init_callback = init; + dequeue_cleanup_callback = cleanup; + has_dequeue_callbacks = true; + } + + // Only valid after configure_card(). + std::string get_description() const { + return description; + } + void configure_card(); void start_bm_capture(); + void stop_dequeue_thread(); static void start_bm_thread(); static void stop_bm_thread(); @@ -112,11 +136,13 @@ class BMUSBCapture { 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(); + void dequeue_thread_func(); static void usb_thread_func(); static void cb_xfr(struct libusb_transfer *xfr); + std::string description; + FrameAllocator::Frame current_video_frame; FrameAllocator::Frame current_audio_frame; @@ -129,13 +155,27 @@ class BMUSBCapture { FrameAllocator *audio_frame_allocator = nullptr; frame_callback_t frame_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]; - int vid, pid; + int card_index; std::vector iso_xfrs; + int assumed_frame_width = 1280; }; +// Get details for the given video format; returns false if detection was incomplete. +// 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). +bool decode_video_format(uint16_t video_format, VideoFormat *decoded_video_format); + #endif