X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bmusb%2Fbmusb.h;h=7a31a4d8372fb249b918bd6dde87d49f83cd834c;hb=c245ceb9081e412bb815480481670e295ddfc71a;hp=21cbc408da0f1190db14cd6d45d94ddfab8ace1a;hpb=92708386b8ea2a63b99c20e6a5f6beff3d9311ac;p=bmusb diff --git a/bmusb/bmusb.h b/bmusb/bmusb.h index 21cbc40..7a31a4d 100644 --- a/bmusb/bmusb.h +++ b/bmusb/bmusb.h @@ -4,11 +4,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -38,7 +40,18 @@ class FrameAllocator { // 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. + // + // This doesn't really make any sense if you asked for the + // 10BitYCbCr pixel format. bool interleaved = false; + + // At what point this frame was received. Note that this marks the + // _end_ of the frame being received, not the beginning. + // Thus, if you want to measure latency, you'll also need to include + // the time the frame actually took to transfer (usually 1/fps, + // ie., the frames are typically transferred in real time). + std::chrono::steady_clock::time_point received_timestamp = + std::chrono::steady_clock::time_point::min(); }; virtual ~FrameAllocator(); @@ -93,14 +106,17 @@ struct VideoMode { // 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 +// "second_field_start" is only valid for interlaced modes. If it is 1, +// the two fields are actually stored interlaced (ie., every other line). +// If not, each field is stored consecutively, and 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; + unsigned stride = 0; // In bytes, assuming no interleaving. bool interlaced = false; bool has_signal = false; bool is_connected = true; // If false, then has_signal makes no sense. @@ -112,6 +128,36 @@ struct AudioFormat { unsigned num_channels = 0; }; +enum PixelFormat { + // 8-bit 4:2:2 in the standard Cb Y Cr Y order (UYVY). + // This is the default. + PixelFormat_8BitYCbCr, + + // 10-bit 4:2:2 in v210 order. Six pixels (six Y', three Cb, + // three Cr) are packed into four 32-bit little-endian ints + // in the following pattern (see e.g. the DeckLink documentation + // for reference): + // + // A B G R + // ----------------- + // X Cr0 Y0 Cb0 + // X Y2 Cb2 Y1 + // X Cb4 Y3 Cr2 + // X Y5 Cr4 Y4 + // + // If you read in RGB order and ignore the unused top bits, + // this is essentially Cb Y Cr Y order, just like UYVY is. + // + // Note that unlike true v210, there is no guarantee about + // 128-byte line alignment (or lack thereof); you should check + // the stride member of VideoFormat. + PixelFormat_10BitYCbCr, + + // 8-bit 4:4:4:4 BGRA (in that order). bmusb itself doesn't + // produce this, but it is useful to represent e.g. synthetic inputs. + PixelFormat_8BitBGRA +}; + typedef std::function @@ -128,6 +174,11 @@ class CaptureInterface { virtual uint32_t get_current_video_mode() const = 0; virtual void set_video_mode(uint32_t video_mode_id) = 0; + // TODO: Add a way to query this based on mode? + virtual std::set get_available_pixel_formats() const = 0; + virtual void set_pixel_format(PixelFormat pixel_format) = 0; + virtual PixelFormat get_current_pixel_format() const = 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; @@ -175,6 +226,22 @@ class BMUSBCapture : public CaptureInterface { ~BMUSBCapture() {} + // Note: Cards could be unplugged and replugged between this call and + // actually opening the card (in configure_card()). + static unsigned num_cards(); + + std::set get_available_pixel_formats() const override + { + return std::set{ PixelFormat_8BitYCbCr, PixelFormat_10BitYCbCr }; + } + + void set_pixel_format(PixelFormat pixel_format) override; + + PixelFormat get_current_pixel_format() const + { + return current_pixel_format; + } + 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; @@ -327,6 +394,7 @@ class BMUSBCapture : public CaptureInterface { libusb_device_handle *devh = nullptr; uint32_t current_video_input = 0x00000000; // HDMI/SDI. uint32_t current_audio_input = 0x00000000; // Embedded. + PixelFormat current_pixel_format = PixelFormat_8BitYCbCr; bool disconnected = false; };