]> git.sesse.net Git - bmusb/blobdiff - fake_capture.cpp
Support 10-bit capture.
[bmusb] / fake_capture.cpp
index 2ef1d7d68dc58b71a2c2cd93a76efd0f5473d536..5f4f5da4ea5904e9d7186eb9eef98003de1644be 100644 (file)
@@ -87,6 +87,26 @@ void memset4(uint8_t *s, const uint8_t c[4], size_t n)
        }
 }
 
+void memset16(uint8_t *s, const uint32_t c[4], size_t n)
+{
+       size_t i = 0;
+#if __SSE2__
+       __m128i cc = *(__m128i *)c;
+       __m128i *out = (__m128i *)s;
+
+       for ( ; i < (n & ~1); i += 2) {
+               _mm_storeu_si128(out++, cc);
+               _mm_storeu_si128(out++, cc);
+       }
+
+       s = (uint8_t *)out;
+#endif
+       for ( ; i < n; ++i) {
+               memcpy(s, c, 16);
+               s += 16;
+       }
+}
+
 }  // namespace
 
 FakeCapture::FakeCapture(unsigned width, unsigned height, unsigned fps, unsigned audio_sample_frequency, int card_index, bool has_audio)
@@ -246,6 +266,11 @@ void FakeCapture::producer_thread_func()
                VideoFormat video_format;
                video_format.width = width;
                video_format.height = height;
+               if (current_pixel_format == PixelFormat_10BitYCbCr) {
+                       video_format.stride = (width + 5) / 6 * 4 * sizeof(uint32_t);
+               } else {
+                       video_format.stride = width * 2;
+               }
                video_format.frame_rate_nom = fps;
                video_format.frame_rate_den = 1;
                video_format.has_signal = true;
@@ -255,14 +280,26 @@ void FakeCapture::producer_thread_func()
                if (video_frame.data != nullptr) {
                        assert(video_frame.size >= width * height * 2);
                        if (video_frame.interleaved) {
+                               assert(current_pixel_format == PixelFormat_8BitYCbCr);
                                uint8_t cbcr[] = { cb, cr };
                                memset2(video_frame.data, cbcr, width * height / 2);
                                memset(video_frame.data2, y, width * height);
                        } else {
-                               uint8_t ycbcr[] = { y, cb, y, cr };
-                               memset4(video_frame.data, ycbcr, width * height / 2);
+                               if (current_pixel_format == PixelFormat_10BitYCbCr) {
+                                       // Just use the 8-bit-values shifted left by 2.
+                                       // It's not 100% correct, but it's close enough.
+                                       uint32_t pix[4];
+                                       pix[0] = (cb << 2) | (y  << 12) | (cr << 22);
+                                       pix[1] = (y  << 2) | (cb << 12) | ( y << 22);
+                                       pix[2] = (cr << 2) | (y  << 12) | (cb << 22);
+                                       pix[3] = (y  << 2) | (cr << 12) | ( y << 22);
+                                       memset16(video_frame.data, pix, video_format.stride * height / sizeof(pix));
+                               } else {
+                                       uint8_t ycbcr[] = { y, cb, y, cr };
+                                       memset4(video_frame.data, ycbcr, width * height / 2);
+                               }
                        }
-                       video_frame.len = width * height * 2;
+                       video_frame.len = video_format.stride * height;
                        video_frame.received_timestamp = timestamp;
                }