6 #include <condition_variable>
12 // An interface for frame allocators; if you do not specify one
13 // (using set_video_frame_allocator), a default one that pre-allocates
14 // a freelist of eight frames using new[] will be used. Specifying
15 // your own can be useful if you have special demands for where you want the
16 // frame to end up and don't want to spend the extra copy to get it there, for
17 // instance GPU memory.
18 class FrameAllocator {
21 uint8_t *data = nullptr;
22 uint8_t *data2 = nullptr; // Only if interleaved == true.
23 size_t len = 0; // Number of bytes we actually have.
24 size_t size = 0; // Number of bytes we have room for.
25 void *userdata = nullptr;
26 FrameAllocator *owner = nullptr;
28 // If set to true, every other byte will go to data and to data2.
29 // If so, <len> and <size> are still about the number of total bytes
30 // so if size == 1024, there's 512 bytes in data and 512 in data2.
31 bool interleaved = false;
34 virtual ~FrameAllocator();
36 // Request a video frame. Note that this is called from the
37 // USB thread, which runs with realtime priority and is
38 // very sensitive to delays. Thus, you should not do anything
39 // here that might sleep, including calling malloc().
40 // (Taking a mutex is borderline.)
42 // The Frame object will be given to the frame callback,
43 // which is responsible for releasing the video frame back
44 // once it is usable for new frames (ie., it will no longer
45 // be read from). You can use the "userdata" pointer for
46 // whatever you want to identify this frame if you need to.
48 // Returning a Frame with data==nullptr is allowed;
49 // if so, the frame in progress will be dropped.
50 virtual Frame alloc_frame() = 0;
52 virtual void release_frame(Frame frame) = 0;
55 typedef std::function<void(uint16_t timecode,
56 FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format,
57 FrameAllocator::Frame audio_frame, size_t audio_offset, uint16_t audio_format)>
60 // The actual capturing class, representing capture from a single card.
63 // Does not take ownership.
64 void set_video_frame_allocator(FrameAllocator *allocator)
66 video_frame_allocator = allocator;
69 FrameAllocator *get_video_frame_allocator()
71 return video_frame_allocator;
74 // Does not take ownership.
75 void set_audio_frame_allocator(FrameAllocator *allocator)
77 audio_frame_allocator = allocator;
80 FrameAllocator *get_audio_frame_allocator()
82 return audio_frame_allocator;
85 void set_frame_callback(frame_callback_t callback)
87 frame_callback = callback;
90 void start_bm_capture();
91 void stop_bm_capture();
97 FrameAllocator::Frame frame;
100 void start_new_audio_block(const uint8_t *start);
101 void start_new_frame(const uint8_t *start);
103 void queue_frame(uint16_t format, uint16_t timecode, FrameAllocator::Frame frame, std::deque<QueuedFrame> *q);
104 void dequeue_thread();
106 void usb_thread_func();
107 static void cb_xfr(struct libusb_transfer *xfr);
109 FrameAllocator::Frame current_video_frame;
110 FrameAllocator::Frame current_audio_frame;
112 std::mutex queue_lock;
113 std::condition_variable queues_not_empty;
114 std::deque<QueuedFrame> pending_video_frames;
115 std::deque<QueuedFrame> pending_audio_frames;
117 std::thread usb_thread;
118 std::atomic<bool> should_quit;
120 FrameAllocator *video_frame_allocator = nullptr;
121 FrameAllocator *audio_frame_allocator = nullptr;
122 frame_callback_t frame_callback = nullptr;
124 int current_register = 0;
126 static constexpr int NUM_BMUSB_REGISTERS = 60;
127 uint8_t register_file[NUM_BMUSB_REGISTERS];