]> git.sesse.net Git - nageru/blobdiff - decklink_capture.cpp
Fix an issue where the mixer lagging too much behind CEF would cause us to display...
[nageru] / decklink_capture.cpp
index 21a4e791a747459ed1a4dee6d81cbc5ced55a680..6dba068fca51108fcbfc3a55050efcc1223880ee 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "bmusb/bmusb.h"
 #include "decklink_util.h"
+#include "flags.h"
+#include "v210_converter.h"
 
 #define FRAME_SIZE (8 << 20)  // 8 MB.
 
@@ -138,6 +140,18 @@ size_t memcpy_interleaved_fastpath(uint8_t *dest1, uint8_t *dest2, const uint8_t
 
 #endif  // __SSE2__
 
+BMDPixelFormat pixel_format_to_bmd(PixelFormat pixel_format)
+{
+       switch (pixel_format) {
+       case PixelFormat_8BitYCbCr:
+               return bmdFormat8BitYUV;
+       case PixelFormat_10BitYCbCr:
+               return bmdFormat10BitYUV;
+       default:
+               assert(false);
+       }
+}
+
 }  // namespace
 
 DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index)
@@ -305,6 +319,14 @@ HRESULT STDMETHODCALLTYPE DeckLinkCapture::VideoInputFrameArrived(
                char thread_name[16];
                snprintf(thread_name, sizeof(thread_name), "DeckLink_C_%d", card_index);
                pthread_setname_np(pthread_self(), thread_name);
+
+               sched_param param;
+               memset(&param, 0, sizeof(param));
+               param.sched_priority = 1;
+               if (sched_setscheduler(0, SCHED_RR, &param) == -1) {
+                       printf("couldn't set realtime priority for DeckLink thread: %s\n", strerror(errno));
+               }
+
                if (has_dequeue_callbacks) {
                        dequeue_init_callback();
                }
@@ -326,10 +348,16 @@ HRESULT STDMETHODCALLTYPE DeckLinkCapture::VideoInputFrameArrived(
        if (video_frame) {
                video_format.has_signal = !(video_frame->GetFlags() & bmdFrameHasNoInputSource);
 
-               int width = video_frame->GetWidth();
-               int height = video_frame->GetHeight();
+               const int width = video_frame->GetWidth();
+               const int height = video_frame->GetHeight();
                const int stride = video_frame->GetRowBytes();
-               assert(stride == width * 2);
+               const BMDPixelFormat format = video_frame->GetPixelFormat();
+               assert(format == pixel_format_to_bmd(current_pixel_format));
+               if (global_flags.ten_bit_input) {
+                       assert(stride == int(v210Converter::get_v210_stride(width)));
+               } else {
+                       assert(stride == width * 2);
+               }
 
                current_video_frame = video_frame_allocator->alloc_frame();
                if (current_video_frame.data != nullptr) {
@@ -362,6 +390,7 @@ HRESULT STDMETHODCALLTYPE DeckLinkCapture::VideoInputFrameArrived(
 
                        video_format.width = width;
                        video_format.height = height;
+                       video_format.stride = stride;
                }
        }
 
@@ -413,7 +442,7 @@ void DeckLinkCapture::start_bm_capture()
        if (running) {
                return;
        }
-       if (input->EnableVideoInput(current_video_mode, bmdFormat8BitYUV, supports_autodetect ? bmdVideoInputEnableFormatDetection : 0) != S_OK) {
+       if (input->EnableVideoInput(current_video_mode, pixel_format_to_bmd(current_pixel_format), supports_autodetect ? bmdVideoInputEnableFormatDetection : 0) != S_OK) {
                fprintf(stderr, "Failed to set video mode 0x%04x for card %d\n", current_video_mode, card_index);
                exit(1);
        }
@@ -452,28 +481,38 @@ void DeckLinkCapture::stop_dequeue_thread()
 
 void DeckLinkCapture::set_video_mode(uint32_t video_mode_id)
 {
-       if (input->PauseStreams() != S_OK) {
-               fprintf(stderr, "PauseStreams failed\n");
-               exit(1);
-       }
-       if (input->FlushStreams() != S_OK) {
-               fprintf(stderr, "FlushStreams failed\n");
-               exit(1);
+       if (running) {
+               if (input->PauseStreams() != S_OK) {
+                       fprintf(stderr, "PauseStreams failed\n");
+                       exit(1);
+               }
+               if (input->FlushStreams() != S_OK) {
+                       fprintf(stderr, "FlushStreams failed\n");
+                       exit(1);
+               }
        }
 
        set_video_mode_no_restart(video_mode_id);
 
-       if (input->StartStreams() != S_OK) {
-               fprintf(stderr, "StartStreams failed\n");
-               exit(1);
+       if (running) {
+               if (input->StartStreams() != S_OK) {
+                       fprintf(stderr, "StartStreams failed\n");
+                       exit(1);
+               }
        }
 }
 
+void DeckLinkCapture::set_pixel_format(PixelFormat pixel_format)
+{
+       current_pixel_format = pixel_format;
+       set_video_mode(current_video_mode);
+}
+
 void DeckLinkCapture::set_video_mode_no_restart(uint32_t video_mode_id)
 {
        BMDDisplayModeSupport support;
        IDeckLinkDisplayMode *display_mode;
-       if (input->DoesSupportVideoMode(video_mode_id, bmdFormat8BitYUV, /*flags=*/0, &support, &display_mode)) {
+       if (input->DoesSupportVideoMode(video_mode_id, pixel_format_to_bmd(current_pixel_format), /*flags=*/0, &support, &display_mode)) {
                fprintf(stderr, "Failed to query display mode for card %d\n", card_index);
                exit(1);
        }
@@ -491,7 +530,7 @@ void DeckLinkCapture::set_video_mode_no_restart(uint32_t video_mode_id)
        field_dominance = display_mode->GetFieldDominance();
 
        if (running) {
-               if (input->EnableVideoInput(video_mode_id, bmdFormat8BitYUV, supports_autodetect ? bmdVideoInputEnableFormatDetection : 0) != S_OK) {
+               if (input->EnableVideoInput(video_mode_id, pixel_format_to_bmd(current_pixel_format), supports_autodetect ? bmdVideoInputEnableFormatDetection : 0) != S_OK) {
                        fprintf(stderr, "Failed to set video mode 0x%04x for card %d\n", video_mode_id, card_index);
                        exit(1);
                }