]> git.sesse.net Git - bmusb/commitdiff
Add a function to get video format details.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 16 Nov 2015 23:59:23 +0000 (00:59 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 16 Nov 2015 23:59:23 +0000 (00:59 +0100)
bmusb.cpp
bmusb.h

index 4621e4b82880ea50189ecbcb07127205683d417f..74adca86c14c603c2c0855c41ba319849365638a 100644 (file)
--- a/bmusb.cpp
+++ b/bmusb.cpp
@@ -1063,3 +1063,89 @@ void BMUSBCapture::stop_bm_thread()
        should_quit = true;
        usb_thread.join();
 }
+
+struct VideoFormatEntry {
+       uint16_t normalized_video_format;
+       int width, height;
+       int frame_rate_den, frame_rate_nom;
+       bool interlaced;
+};
+
+bool decode_video_format(uint16_t video_format, int *width, int *height, int *frame_rate_den, int *frame_rate_nom, bool *interlaced)
+{
+       *interlaced = false;
+
+       if (video_format == 0x0800) {
+               // No video signal. These green pseudo-frames seem to come at about 30.13 Hz.
+               // It's a strange thing, but what can you do.
+               // FIXME: find the dimensions.
+               *frame_rate_nom = 3013;
+               *frame_rate_den = 100;
+               return true;
+       }
+       if ((video_format & 0xe800) != 0xe800) {
+               printf("Video format 0x%04x does not appear to be a video format. Assuming 60 Hz.\n",
+                       video_format);
+               *width = 0;
+               *height = 0;
+               *frame_rate_nom = 60;
+               *frame_rate_den = 1;
+               return false;
+       }
+
+       // NTSC (480i59.94, I suppose). A special case, see below.
+       if (video_format == 0xe901 || video_format == 0xe9c1 || video_format == 0xe801) {
+               *width = 640;
+               *height = 480;
+               *frame_rate_nom = 60000;
+               *frame_rate_den = 1001;
+               *interlaced = true;
+               return true;
+       }
+
+       // PAL (576i50, I suppose). A special case, see below.
+       if (video_format == 0xe909) {
+               *width = 720;
+               *height = 576;
+               *frame_rate_nom = 50;
+               *frame_rate_den = 1;
+               *interlaced = true;
+               return true;
+       }
+
+       // 0x8 seems to be a flag about availability of deep color on the input,
+       // except when it's not (e.g. it's the only difference between NTSC
+       // and PAL). Rather confusing. But we clear it here nevertheless, because
+       // usually it doesn't mean anything.
+       uint16_t normalized_video_format = video_format & ~0xe808;
+       constexpr VideoFormatEntry entries[] = {
+               { 0x0143, 1280,  720,    50,    1, false },  // 720p50.
+               { 0x0103, 1280,  720,    60,    1, false },  // 720p60.
+               { 0x0121, 1280,  720, 60000, 1001, false },  // 720p59.94.
+               { 0x01c3, 1920, 1080,    30,    1, false },  // 1080p30.
+               { 0x0003, 1920, 1080,    30,    1,  true },  // 1080i60.
+               { 0x01e1, 1920, 1080, 30000, 1001, false },  // 1080p29.97.
+               { 0x0021, 1920, 1080, 30000, 1001,  true },  // 1080i59.94.
+               { 0x0063, 1920, 1080,    25,    1, false },  // 1080p25.
+               { 0x0043, 1920, 1080,    25,    1,  true },  // 1080p50.
+               { 0x008e, 1920, 1080,    24,    1, false },  // 1080p24.
+               { 0x00a1, 1920, 1080, 24000, 1001, false },  // 1080p23.98.
+       };
+       for (const VideoFormatEntry &entry : entries) {
+               if (normalized_video_format == entry.normalized_video_format) {
+                       *width = entry.width;
+                       *height = entry.height;
+                       *frame_rate_nom = entry.frame_rate_nom;
+                       *frame_rate_den = entry.frame_rate_den;
+                       *interlaced = entry.interlaced;
+                       return true;
+               }
+       }
+
+       printf("Unknown video format 0x%04x. Assuming 720p60.\n", video_format);
+       *width = 1280;
+       *height = 720;
+       *frame_rate_nom = 60;
+       *frame_rate_den = 1;
+       return false;
+}
diff --git a/bmusb.h b/bmusb.h
index e2033264ad45443528fe97a494a38bd06e0f089a..9eb3ff4f716a4ede88c997f65131c6fe69232179 100644 (file)
--- a/bmusb.h
+++ b/bmusb.h
@@ -154,4 +154,8 @@ class BMUSBCapture {
        std::vector<libusb_transfer *> iso_xfrs;
 };
 
+// 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.
+bool decode_video_format(uint16_t video_format, int *width, int *height, int *frame_rate_nom, int *frame_rate_den, bool *interlaced);
+
 #endif