From 749da82ee5ae8bfd9d5f755dc6693369a8412f69 Mon Sep 17 00:00:00 2001 From: James Wise Date: Mon, 13 Feb 2017 14:27:27 +1100 Subject: [PATCH] Buffer Depth stuff: new defined values: BLUEFISH_HW_BUFFER_DEPTH 1 BLUEFISH_SOFTWARE_BUFFERS 4 To easily set the HW buffer depth, and number of software buffers used. Previous setting of 3 for the HW buffer depth has been reduced to 1, since almost all hardware tested shows that 1 is sufficient. ( very old machines with poor PCI performance may struggle with a buffer of just 1) bluefish_consumer_proxy::buffer_depth now returns the correct value, ie. BLUEFISH_HW_BUFFER_DEPTH ( i have tested this via taking a pic of both screen and SDI display, and confirming that they both display the same frame, I hope this is the correct use/interpretation of this value) Queue, Mutex and thread stuff: Changed the std::queue and std::mutex to use tbb:concurrent_counded_queue, as suggested. This has greatly simplified the code by removing the mutex's and associated lock/unlock calls. made the end_dma_thread bool, tbb::atomeic too - should have always been marked as such, or at least volatile. also added code to specifically set the maximum size for the tbb concurrent queue Mofified the way we allocate the std::thread for the DMA and present. thread is now a class member which makes things a bit cleaner too. removed the mutex and lock stuff from this too. Startup uses the Dfeined buffer value from top of file. Routing and card config: Minor change to the way we woncfigure routing on neutron cards when using the hw keyer, 2nd link ie. the fill only now gets routed correctly. Hardware Keyer: Now using the correct Macro to setup the hw Keyer, Be aware the terminology can be confusing as the the macro refers to the source data, not the process to be applied. This has been tested with the casper 1080_test.tga file and produces the correct output. Ie. we see the following text in white. "Alpha / Key correct: Premultipled Linear / Additive" --- .../bluefish/consumer/bluefish_consumer.cpp | 141 +++++++++--------- 1 file changed, 68 insertions(+), 73 deletions(-) diff --git a/modules/bluefish/consumer/bluefish_consumer.cpp b/modules/bluefish/consumer/bluefish_consumer.cpp index 98817c677..fc14714a6 100644 --- a/modules/bluefish/consumer/bluefish_consumer.cpp +++ b/modules/bluefish/consumer/bluefish_consumer.cpp @@ -56,6 +56,9 @@ #include namespace caspar { namespace bluefish { + +#define BLUEFISH_HW_BUFFER_DEPTH 1 +#define BLUEFISH_SOFTWARE_BUFFERS 4 enum class hardware_downstream_keyer_mode { @@ -117,41 +120,39 @@ bool get_videooutput_channel_routing_info_from_streamid(bluefish_hardware_output struct bluefish_consumer : boost::noncopyable { - spl::shared_ptr blue_; - const unsigned int device_index_; - const core::video_format_desc format_desc_; - const core::audio_channel_layout channel_layout_; - core::audio_channel_remapper channel_remapper_; - const int channel_index_; - - const std::wstring model_name_; - - spl::shared_ptr graph_; - boost::timer frame_timer_; - boost::timer tick_timer_; - boost::timer sync_timer_; + spl::shared_ptr blue_; + const unsigned int device_index_; + const core::video_format_desc format_desc_; + const core::audio_channel_layout channel_layout_; + core::audio_channel_remapper channel_remapper_; + const int channel_index_; + + const std::wstring model_name_; + + spl::shared_ptr graph_; + boost::timer frame_timer_; + boost::timer tick_timer_; + boost::timer sync_timer_; - unsigned int vid_fmt_; - - std::array all_frames_; - std::queue reserved_frames_; - std::mutex reserved_frames_lock_; - std::queue live_frames_; - std::mutex live_frames_lock_; - std::shared_ptr dma_present_thread_; - bool end_dma_thread_; - - tbb::concurrent_bounded_queue frame_buffer_; - tbb::atomic presentation_delay_millis_; - core::const_frame previous_frame_ = core::const_frame::empty(); - - const bool embedded_audio_; - const bool key_only_; + unsigned int vid_fmt_; + + std::array all_frames_; + tbb::concurrent_bounded_queue reserved_frames_; + tbb::concurrent_bounded_queue live_frames_; + std::shared_ptr dma_present_thread_; + tbb::atomic end_dma_thread_; + + tbb::concurrent_bounded_queue frame_buffer_; + tbb::atomic presentation_delay_millis_; + core::const_frame previous_frame_ = core::const_frame::empty(); + + const bool embedded_audio_; + const bool key_only_; - executor executor_; - hardware_downstream_keyer_mode hardware_keyer_; - hardware_downstream_keyer_audio_source keyer_audio_source_; - bluefish_hardware_output_channel device_output_channel_; + executor executor_; + hardware_downstream_keyer_mode hardware_keyer_; + hardware_downstream_keyer_audio_source keyer_audio_source_; + bluefish_hardware_output_channel device_output_channel_; public: bluefish_consumer( const core::video_format_desc& format_desc, @@ -182,6 +183,9 @@ public: executor_.set_capacity(1); presentation_delay_millis_ = 0; + reserved_frames_.set_capacity(BLUEFISH_SOFTWARE_BUFFERS); + live_frames_.set_capacity(BLUEFISH_SOFTWARE_BUFFERS); + graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_color("sync-time", diagnostics::color(1.0f, 0.0f, 0.0f)); graph_->set_color("frame-time", diagnostics::color(0.5f, 1.0f, 0.2f)); @@ -302,7 +306,7 @@ public: bool duallink_4224_enabled = false; if ((device_output_channel_ == bluefish_hardware_output_channel::channel_a || device_output_channel_ == bluefish_hardware_output_channel::channel_c) && - (hardware_keyer_ == hardware_downstream_keyer_mode::external)) + (hardware_keyer_ == hardware_downstream_keyer_mode::external) || (hardware_keyer_ == hardware_downstream_keyer_mode::internal) ) { duallink_4224_enabled = true; } @@ -397,6 +401,10 @@ public: if (BLUE_FAIL(blue_->get_card_property32(INVALID_VIDEO_MODE_FLAG, invalidVideoModeFlag))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to get invalid video mode flag")); + // The bluefish HW keyer is going to pre-multiply the RGB with the A. + // This setting results in the correct image coming through when using the 1080_test.tga image. + keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_NOT_PREMULTIPLIED(keyer_control_value); + keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(keyer_control_value); if (BLUE_FAIL(blue_->get_card_property32(VIDEO_INPUT_SIGNAL_VIDEO_MODE, inputVideoSignal))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to get video input signal mode")); @@ -455,62 +463,54 @@ public: }); } - static void dma_present_thread_actual(void* arg) + void dma_present_thread_actual() { - bluefish_consumer* blue = (bluefish_consumer*)arg; - bvc_wrapper wait_b; - wait_b.attach(blue->device_index_); - EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(blue->device_output_channel_); + wait_b.attach(device_index_); + EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(device_output_channel_); wait_b.set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel); - int frames_to_buffer = 3; + int frames_to_buffer = BLUEFISH_HW_BUFFER_DEPTH; unsigned long buffer_id = 0; unsigned long underrun = 0; - while (!blue->end_dma_thread_) + while (!end_dma_thread_) { - if (blue->live_frames_.size() && BLUE_OK(blue->blue_->video_playback_allocate(buffer_id, underrun))) + if (!live_frames_.empty() && BLUE_OK(blue_->video_playback_allocate(buffer_id, underrun))) { - blue->live_frames_lock_.lock(); - blue_dma_buffer_ptr buf = blue->live_frames_.front(); - blue->live_frames_.pop(); - blue->live_frames_lock_.unlock(); + blue_dma_buffer_ptr buf = nullptr; + live_frames_.pop(buf); // Send and display - if (blue->embedded_audio_) + if (embedded_audio_) { - // Do video first, then encode hanc, then do hanc DMA... - blue->blue_->system_buffer_write(const_cast(buf->image_data()), + // Do video first, then do hanc DMA... + blue_->system_buffer_write(const_cast(buf->image_data()), static_cast(buf->image_size()), BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_IMAGE), 0); - blue->blue_->system_buffer_write(buf->hanc_data(), + blue_->system_buffer_write(buf->hanc_data(), static_cast(buf->hanc_size()), BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_HANC), 0); - if (BLUE_FAIL(blue->blue_->video_playback_present(BlueBuffer_Image_HANC(buffer_id), 1, 0, 0))) + if (BLUE_FAIL(blue_->video_playback_present(BlueBuffer_Image_HANC(buffer_id), 1, 0, 0))) { - CASPAR_LOG(warning) << blue->print() << TEXT(" video_playback_present failed."); + CASPAR_LOG(warning) << print() << TEXT(" video_playback_present failed."); } } else { - blue->blue_->system_buffer_write(const_cast(buf->image_data()), + blue_->system_buffer_write(const_cast(buf->image_data()), static_cast(buf->image_size()), BlueImage_DMABuffer(buffer_id, BLUE_DATA_IMAGE), 0); - if (BLUE_FAIL(blue->blue_->video_playback_present(BlueBuffer_Image(buffer_id), 1, 0, 0))) - CASPAR_LOG(warning) << blue->print() << TEXT(" video_playback_present failed."); + if (BLUE_FAIL(blue_->video_playback_present(BlueBuffer_Image(buffer_id), 1, 0, 0))) + CASPAR_LOG(warning) << print() << TEXT(" video_playback_present failed."); } - // blue->graph_->set_value("frame-time", static_cast(blue->frame_timer_.elapsed()*blue->format_desc_.fps*0.5)); - - blue->reserved_frames_lock_.lock(); - blue->reserved_frames_.push(buf); - blue->reserved_frames_lock_.unlock(); + reserved_frames_.push(buf); } else { @@ -524,8 +524,8 @@ public: frames_to_buffer--; if (frames_to_buffer == 0) { - if (BLUE_FAIL(blue->blue_->video_playback_start(0, 0))) - CASPAR_LOG(warning) << blue->print() << TEXT("Error video playback start failed"); + if (BLUE_FAIL(blue_->video_playback_start(0, 0))) + CASPAR_LOG(warning) << print() << TEXT("Error video playback start failed"); } } } @@ -542,12 +542,10 @@ public: previous_frame_ = frame; // Copy to local buffers - if (reserved_frames_.size()) + if (!reserved_frames_.empty()) { - reserved_frames_lock_.lock(); - blue_dma_buffer_ptr buf = reserved_frames_.front(); - reserved_frames_.pop(); - reserved_frames_lock_.unlock(); + blue_dma_buffer_ptr buf = nullptr; + reserved_frames_.pop(buf); void* dest = buf->image_data(); if (!frame.image_data().empty()) @@ -558,7 +556,7 @@ public: A_memcpy(dest, frame.image_data().begin(), frame.image_data().size()); } else - A_memset(dest, 0, reserved_frames_.front()->image_size()); + A_memset(dest, 0, buf->image_size()); frame_timer_.restart(); @@ -572,16 +570,13 @@ public: static_cast(frame.audio_data().size() / channel_layout_.num_channels), static_cast(channel_layout_.num_channels)); } - - live_frames_lock_.lock(); live_frames_.push(buf); - live_frames_lock_.unlock(); // start the thread if required. if (dma_present_thread_ == 0) { end_dma_thread_ = false; - dma_present_thread_ = std::make_shared(&dma_present_thread_actual, this); + dma_present_thread_ = std::make_shared([this] {dma_present_thread_actual(); }); #if defined(_WIN32) HANDLE handle = (HANDLE)dma_present_thread_->native_handle(); SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST); @@ -729,7 +724,7 @@ public: int buffer_depth() const override { - return 1; + return BLUEFISH_HW_BUFFER_DEPTH; } int index() const override -- 2.39.2