+
+ void setup_hardware_output_channel()
+ {
+ // This function would be used to setup the logic video channel in the bluefish hardware
+ EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(device_output_channel_);
+ if (is_epoch_card((*blue_)))
+ {
+ if (out_vid_channel != BLUE_VIDEOCHANNEL_INVALID)
+ {
+ if (BLUE_FAIL(blue_->set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to set video stream."));
+
+ blue_->video_playback_stop(0, 0);
+ }
+ }
+ }
+
+ void setup_hardware_output_channel_routing()
+ {
+ //This function would be used to setup the dual link and any other routing that would be required .
+ if (is_epoch_card(*blue_))
+ {
+ EBlueVideoChannel blueVideoOutputChannel = get_bluesdk_videochannel_from_streamid(device_output_channel_);
+ EEpochRoutingElements src_element = (EEpochRoutingElements)0;
+ EEpochRoutingElements dst_element = (EEpochRoutingElements)0;
+ get_videooutput_channel_routing_info_from_streamid(device_output_channel_, src_element, dst_element);
+ 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::internal) )
+ {
+ duallink_4224_enabled = true;
+ }
+
+ // Enable/Disable dual link output
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT, duallink_4224_enabled)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to enable/disable dual link."));
+
+ if (!duallink_4224_enabled)
+ {
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_Independent_422)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set dual link format type to 4:2:2."));
+
+ ULONG routingValue = EPOCH_SET_ROUTING(src_element, dst_element, BLUE_CONNECTOR_PROP_SINGLE_LINK);
+ if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routingValue)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to MR 2 routing."));
+
+ // If single link 422, but on second channel AND on Neutron we need to set Genlock to Aux.
+ if (is_epoch_neutron_1i2o_card((*blue_)))
+ {
+ if (blueVideoOutputChannel == BLUE_VIDEO_OUTPUT_CHANNEL_B)
+ {
+ ULONG genLockSource = BlueGenlockAux;
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input."));
+ }
+ }
+ if (is_epoch_neutron_3o_card((*blue_)))
+ {
+ if (blueVideoOutputChannel == BLUE_VIDEO_OUTPUT_CHANNEL_C)
+ {
+ ULONG genLockSource = BlueGenlockAux;
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input."));
+ }
+ }
+ }
+ else // dual Link IS enabled, ie. 4224 Fill and Key
+ {
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_4224)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set dual link format type to 4:2:2:4."));
+
+ if (is_epoch_neutron_1i2o_card((*blue_))) // Neutron cards require setting the Genlock conector to Aux to enable them to do Dual-Link
+ {
+ ULONG genLockSource = BlueGenlockAux;
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input."));
+ }
+ else if (is_epoch_neutron_3o_card((*blue_)))
+ {
+ if (blueVideoOutputChannel == BLUE_VIDEO_OUTPUT_CHANNEL_C)
+ {
+ ULONG genLockSource = BlueGenlockAux;
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input."));
+ }
+ }
+ }
+ }
+ }
+
+ void setup_hardware_downstream_keyer(hardware_downstream_keyer_mode keyer, hardware_downstream_keyer_audio_source audio_source)
+ {
+ unsigned int keyer_control_value = 0, card_feature_value = 0;
+ unsigned int card_connector_value = 0;
+ unsigned int nOutputStreams = 0;
+ unsigned int nInputStreams = 0;
+ unsigned int nInputSDIConnector = 0;
+ unsigned int nOutputSDIConnector = 0;
+ if (BLUE_OK(blue_->get_card_property32(CARD_FEATURE_STREAM_INFO, card_feature_value)))
+ {
+ nOutputStreams = CARD_FEATURE_GET_SDI_OUTPUT_STREAM_COUNT(card_feature_value);
+ nInputStreams = CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(card_feature_value);
+ }
+ if (BLUE_OK(blue_->get_card_property32(CARD_FEATURE_CONNECTOR_INFO, card_connector_value)))
+ {
+ nOutputSDIConnector = CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(card_connector_value);
+ nInputSDIConnector = CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(card_connector_value);
+ }
+ if (nInputSDIConnector == 0 || nInputStreams == 0)
+ return;
+
+ if (keyer == hardware_downstream_keyer_mode::disable || keyer == hardware_downstream_keyer_mode::external)
+ {
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLED(keyer_control_value);
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value);
+ }
+ else if (keyer == hardware_downstream_keyer_mode::internal)
+ {
+ unsigned int invalidVideoModeFlag = 0;
+ unsigned int inputVideoSignal = 0;
+ 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 NOT going to pre-multiply the RGB with the A.
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_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"));
+
+ if (inputVideoSignal >= invalidVideoModeFlag)
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLE_OVER_BLACK(keyer_control_value);
+ else
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value);
+
+ // lock to input
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, BlueSDI_A_BNC)))
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to set the genlock to the input for the HW keyer"));
+ }
+
+ if (audio_source == hardware_downstream_keyer_audio_source::SDIVideoInput && (keyer == hardware_downstream_keyer_mode::internal))
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_INPUT_ANCILLARY(keyer_control_value);
+ else if (audio_source == hardware_downstream_keyer_audio_source::VideoOutputChannel)
+ keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_OUTPUT_ANCILLARY(keyer_control_value);
+
+ if (BLUE_FAIL(blue_->set_card_property32(VIDEO_ONBOARD_KEYER, keyer_control_value)))
+ CASPAR_LOG(error) << print() << TEXT(" Failed to set keyer control.");
+ }
+