]> git.sesse.net Git - nageru/blobdiff - bmusb.cpp
Support arbitrary SBS zooming (ie., zooming in on the little picture, too).
[nageru] / bmusb.cpp
index a31d260b7c7f82ab52c53b99dc069d1c8d600a33..03f8fd210120da980f66f2c4eeab8cde2eed5967 100644 (file)
--- a/bmusb.cpp
+++ b/bmusb.cpp
@@ -15,7 +15,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef __SSE2__
+#ifdef __SSE4_1__
 #include <immintrin.h>
 #endif
 #include "bmusb.h"
@@ -146,11 +146,14 @@ void dump_audio_block(uint8_t *audio_start, size_t audio_len)
        fwrite(audio_start + AUDIO_HEADER_SIZE, 1, audio_len - AUDIO_HEADER_SIZE, audiofp);
 }
 
-void BMUSBCapture::dequeue_thread()
+void BMUSBCapture::dequeue_thread_func()
 {
-       for ( ;; ) {
+       if (has_dequeue_callbacks) {
+               dequeue_init_callback();
+       }
+       while (!dequeue_thread_should_quit) {
                unique_lock<mutex> lock(queue_lock);
-               queues_not_empty.wait(lock, [this]{ return !pending_video_frames.empty() && !pending_audio_frames.empty(); });
+               queues_not_empty.wait(lock, [this]{ return dequeue_thread_should_quit || (!pending_video_frames.empty() && !pending_audio_frames.empty()); });
 
                uint16_t video_timecode = pending_video_frames.front().timecode;
                uint16_t audio_timecode = pending_audio_frames.front().timecode;
@@ -183,6 +186,9 @@ void BMUSBCapture::dequeue_thread()
                                       audio_frame.frame, AUDIO_HEADER_SIZE, audio_frame.format);
                }
        }
+       if (has_dequeue_callbacks) {
+               dequeue_cleanup_callback();
+       }
 }
 
 void BMUSBCapture::start_new_frame(const uint8_t *start)
@@ -285,10 +291,10 @@ void add_to_frame(FrameAllocator::Frame *current_frame, const char *frame_type_n
        }
 }
 
-#ifdef __SSE2__
+#ifdef __SSE4_1__
 
 #if 0
-void dump(const char *name, __m256i n)
+void avx2_dump(const char *name, __m256i n)
 {
        printf("%-10s:", name);
        printf(" %02x", _mm256_extract_epi8(n, 0));
@@ -519,7 +525,7 @@ void decode_packs(const libusb_transfer *xfr,
                const uint8_t *start = xfr->buffer + offset;
                const uint8_t *limit = start + pack->actual_length;
                while (start < limit) {  // Usually runs only one iteration.
-#ifdef __SSE2__
+#ifdef __SSE4_1__
                        start = add_to_frame_fastpath(current_frame, start, limit, sync_pattern[0]);
                        if (start == limit) break;
                        assert(start < limit);
@@ -630,7 +636,8 @@ void BMUSBCapture::configure_card()
        if (audio_frame_allocator == nullptr) {
                set_audio_frame_allocator(new MallocFrameAllocator(65536));  // FIXME: leak.
        }
-       thread(&BMUSBCapture::dequeue_thread, this).detach();
+       dequeue_thread_should_quit = false;
+       dequeue_thread = thread(&BMUSBCapture::dequeue_thread_func, this);
 
        int rc;
        struct libusb_transfer *xfr;
@@ -669,13 +676,11 @@ void BMUSBCapture::configure_card()
                }
        }
 
-#if 0
        rc = libusb_set_configuration(devh, /*configuration=*/1);
        if (rc < 0) {
                fprintf(stderr, "Error setting configuration 1: %s\n", libusb_error_name(rc));
                exit(1);
        }
-#endif
 
        rc = libusb_claim_interface(devh, 0);
        if (rc < 0) {
@@ -683,6 +688,22 @@ void BMUSBCapture::configure_card()
                exit(1);
        }
 
+       // Alternate setting 1 is output, alternate setting 2 is input.
+       // Card is reset when switching alternates, so the driver uses
+       // this “double switch” when it wants to reset.
+       //
+       // There's also alternate settings 3 and 4, which seem to be
+       // like 1 and 2 except they advertise less bandwidth needed.
+       rc = libusb_set_interface_alt_setting(devh, /*interface=*/0, /*alternate_setting=*/1);
+       if (rc < 0) {
+               fprintf(stderr, "Error setting alternate 1: %s\n", libusb_error_name(rc));
+               exit(1);
+       }
+       rc = libusb_set_interface_alt_setting(devh, /*interface=*/0, /*alternate_setting=*/2);
+       if (rc < 0) {
+               fprintf(stderr, "Error setting alternate 1: %s\n", libusb_error_name(rc));
+               exit(1);
+       }
 #if 0
        rc = libusb_set_interface_alt_setting(devh, /*interface=*/0, /*alternate_setting=*/1);
        if (rc < 0) {
@@ -720,6 +741,8 @@ void BMUSBCapture::configure_card()
        //
        //    so only first 16 bits count, and 0x0100 is a mask for ok/stable signal?
        //
+       //    Bottom 16 bits of this register seem to be firmware version number (possibly not all all of them).
+       //
        //    28 and 32 seems to be analog audio input levels (one byte for each of the eight channels).
        //    however, if setting 32 with HDMI embedded audio, it is immediately overwritten back (to 0xe137002a).
        //
@@ -729,6 +752,11 @@ void BMUSBCapture::configure_card()
        //    36 can be set to 0 with no apparent effect (all of this tested on both video and audio),
        //    but the driver sets it to 0x8036802a at some point.
        //
+       //    all of this is on request 214/215. other requests (192, 219,
+       //    222, 223, 224) are used for firmware upgrade. Probably best to
+       //    stay out of it unless you know what you're doing.
+       //
+       //
        // register 16:
        // first byte is 0x39 for a stable 576p60 signal, 0x2d for a stable 720p60 signal, 0x20 for no signal
        //
@@ -783,22 +811,6 @@ void BMUSBCapture::configure_card()
                printf("\n");
        }
 
-       // Alternate setting 1 is output, alternate setting 2 is input.
-       // Card is reset when switching alternates, so the driver uses
-       // this “double switch” when it wants to reset.
-#if 0
-       rc = libusb_set_interface_alt_setting(devh, /*interface=*/0, /*alternate_setting=*/1);
-       if (rc < 0) {
-               fprintf(stderr, "Error setting alternate 1: %s\n", libusb_error_name(rc));
-               exit(1);
-       }
-#endif
-       rc = libusb_set_interface_alt_setting(devh, /*interface=*/0, /*alternate_setting=*/4);
-       if (rc < 0) {
-               fprintf(stderr, "Error setting alternate 4: %s\n", libusb_error_name(rc));
-               exit(1);
-       }
-
 #if 0
        // DEBUG
        for ( ;; ) {
@@ -862,7 +874,7 @@ void BMUSBCapture::configure_card()
        // set up isochronous transfers for audio and video
        for (int e = 3; e <= 4; ++e) {
                //int num_transfers = (e == 3) ? 6 : 6;
-               int num_transfers = 2;
+               int num_transfers = 6;
                for (int i = 0; i < num_transfers; ++i) {
                        int num_iso_pack, size;
                        if (e == 3) {
@@ -928,6 +940,13 @@ out:
 #endif
 }
 
+void BMUSBCapture::stop_dequeue_thread()
+{
+       dequeue_thread_should_quit = true;
+       queues_not_empty.notify_all();  
+       dequeue_thread.join();
+}
+
 void BMUSBCapture::start_bm_thread()
 {
        should_quit = false;