X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bmusb.cpp;h=1079f2aa60932197799855c5b683470223a8c4ad;hb=cd863aa837174f6a3fa5862323d82dab8f0030f8;hp=00f06e443f387f1b0218ae8284a53b00a7b173da;hpb=f9218bdaa19f2c286ca3e2b05c156960edfa0780;p=bmusb diff --git a/bmusb.cpp b/bmusb.cpp index 00f06e4..1079f2a 100644 --- a/bmusb.cpp +++ b/bmusb.cpp @@ -4,29 +4,31 @@ // 576p60/720p60/1080i60 works, 1080p60 does not work (firmware limitation) // Audio comes out as 8-channel 24-bit raw audio. +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include #include -#include -#include -#include -#ifdef __SSE2__ +#ifdef __SSE4_1__ #include #endif +#include "bmusb.h" + #include +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include -#include #include -#include -#include "bmusb.h" +#include using namespace std; using namespace std::placeholders; @@ -45,6 +47,9 @@ using namespace std::placeholders; FILE *audiofp; +thread usb_thread; +atomic should_quit; + FrameAllocator::~FrameAllocator() {} #define NUM_QUEUED_FRAMES 8 @@ -139,11 +144,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 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; @@ -176,6 +184,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) @@ -278,7 +289,50 @@ void add_to_frame(FrameAllocator::Frame *current_frame, const char *frame_type_n } } -#ifdef __SSE2__ +#ifdef __SSE4_1__ + +#if 0 +void avx2_dump(const char *name, __m256i n) +{ + printf("%-10s:", name); + printf(" %02x", _mm256_extract_epi8(n, 0)); + printf(" %02x", _mm256_extract_epi8(n, 1)); + printf(" %02x", _mm256_extract_epi8(n, 2)); + printf(" %02x", _mm256_extract_epi8(n, 3)); + printf(" %02x", _mm256_extract_epi8(n, 4)); + printf(" %02x", _mm256_extract_epi8(n, 5)); + printf(" %02x", _mm256_extract_epi8(n, 6)); + printf(" %02x", _mm256_extract_epi8(n, 7)); + printf(" "); + printf(" %02x", _mm256_extract_epi8(n, 8)); + printf(" %02x", _mm256_extract_epi8(n, 9)); + printf(" %02x", _mm256_extract_epi8(n, 10)); + printf(" %02x", _mm256_extract_epi8(n, 11)); + printf(" %02x", _mm256_extract_epi8(n, 12)); + printf(" %02x", _mm256_extract_epi8(n, 13)); + printf(" %02x", _mm256_extract_epi8(n, 14)); + printf(" %02x", _mm256_extract_epi8(n, 15)); + printf(" "); + printf(" %02x", _mm256_extract_epi8(n, 16)); + printf(" %02x", _mm256_extract_epi8(n, 17)); + printf(" %02x", _mm256_extract_epi8(n, 18)); + printf(" %02x", _mm256_extract_epi8(n, 19)); + printf(" %02x", _mm256_extract_epi8(n, 20)); + printf(" %02x", _mm256_extract_epi8(n, 21)); + printf(" %02x", _mm256_extract_epi8(n, 22)); + printf(" %02x", _mm256_extract_epi8(n, 23)); + printf(" "); + printf(" %02x", _mm256_extract_epi8(n, 24)); + printf(" %02x", _mm256_extract_epi8(n, 25)); + printf(" %02x", _mm256_extract_epi8(n, 26)); + printf(" %02x", _mm256_extract_epi8(n, 27)); + printf(" %02x", _mm256_extract_epi8(n, 28)); + printf(" %02x", _mm256_extract_epi8(n, 29)); + printf(" %02x", _mm256_extract_epi8(n, 30)); + printf(" %02x", _mm256_extract_epi8(n, 31)); + printf("\n"); +} +#endif // Does a memcpy and memchr in one to reduce processing time. // Note that the benefit is somewhat limited if your L3 cache is small, @@ -469,7 +523,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); @@ -559,8 +613,6 @@ void BMUSBCapture::cb_xfr(struct libusb_transfer *xfr) void BMUSBCapture::usb_thread_func() { - printf("usb thread started\n"); - sched_param param; memset(¶m, 0, sizeof(param)); param.sched_priority = 1; @@ -574,7 +626,7 @@ void BMUSBCapture::usb_thread_func() } } -void BMUSBCapture::start_bm_capture() +void BMUSBCapture::configure_card() { if (video_frame_allocator == nullptr) { set_video_frame_allocator(new MallocFrameAllocator(FRAME_SIZE)); // FIXME: leak. @@ -582,11 +634,11 @@ void BMUSBCapture::start_bm_capture() 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; - vector iso_xfrs; rc = libusb_init(nullptr); if (rc < 0) { @@ -594,7 +646,9 @@ void BMUSBCapture::start_bm_capture() exit(1); } - struct libusb_device_handle *devh = libusb_open_device_with_vid_pid(nullptr, 0x1edb, 0xbd3b); + //struct libusb_device_handle *devh = libusb_open_device_with_vid_pid(nullptr, 0x1edb, 0xbd3b); + //struct libusb_device_handle *devh = libusb_open_device_with_vid_pid(nullptr, 0x1edb, 0xbd4f); + struct libusb_device_handle *devh = libusb_open_device_with_vid_pid(nullptr, vid, pid); if (!devh) { fprintf(stderr, "Error finding USB device\n"); exit(1); @@ -635,6 +689,9 @@ void BMUSBCapture::start_bm_capture() // 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)); @@ -829,7 +886,7 @@ void BMUSBCapture::start_bm_capture() size &= ~1023; size += 1024; } - num_iso_pack = (2 << 20) / size; // 2 MB. + num_iso_pack = (2 << 18) / size; // 512 kB. printf("Picking %d packets of 0x%x bytes each\n", num_iso_pack, size); } else { size = 0xc0; @@ -852,24 +909,24 @@ void BMUSBCapture::start_bm_capture() iso_xfrs.push_back(xfr); } } +} - { - int i = 0; - for (libusb_transfer *xfr : iso_xfrs) { - rc = libusb_submit_transfer(xfr); - ++i; - if (rc < 0) { - //printf("num_bytes=%d\n", num_bytes); - fprintf(stderr, "Error submitting iso to endpoint 0x%02x, number %d: %s\n", - xfr->endpoint, i, libusb_error_name(rc)); - exit(1); - } +void BMUSBCapture::start_bm_capture() +{ + printf("starting capture\n"); + int i = 0; + for (libusb_transfer *xfr : iso_xfrs) { + printf("submitting transfer...\n"); + int rc = libusb_submit_transfer(xfr); + ++i; + if (rc < 0) { + //printf("num_bytes=%d\n", num_bytes); + fprintf(stderr, "Error submitting iso to endpoint 0x%02x, number %d: %s\n", + xfr->endpoint, i, libusb_error_name(rc)); + exit(1); } } - should_quit = false; - usb_thread = thread(&BMUSBCapture::usb_thread_func, this); - #if 0 libusb_release_interface(devh, 0); @@ -881,7 +938,20 @@ out: #endif } -void BMUSBCapture::stop_bm_capture() +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; + usb_thread = thread(&BMUSBCapture::usb_thread_func); +} + +void BMUSBCapture::stop_bm_thread() { should_quit = true; usb_thread.join();