]> git.sesse.net Git - casparcg/commitdiff
Modifications to the files within the Bluefish module.
authorJames Wise <james.wise@bluefish444.com>
Sun, 29 Jan 2017 17:59:08 +0000 (04:59 +1100)
committerJames Wise <james.wise@bluefish444.com>
Sun, 29 Jan 2017 17:59:08 +0000 (04:59 +1100)
Changed the Bluefish internal stuff to use the BlueVelvetC API.
Now using an internal class ( BVCWrapper)  that contains function pointers, so module will only get loaded if BF hardware and driver is present.
Updated inner workings to better support latest and different version of bluefish hardware.
Added support for using multiple channels
Added support multiple cards.
Added support for using the onboard keyer
Improved routing and configuration.

modules/CMakeLists.txt
modules/bluefish/CMakeLists.txt
modules/bluefish/bluefish.cpp
modules/bluefish/consumer/bluefish_consumer.cpp
modules/bluefish/consumer/bluefish_consumer.h
modules/bluefish/util/blue_velvet.cpp
modules/bluefish/util/blue_velvet.h
modules/bluefish/util/memory.h

index 8dd4a84209b59da78955e588df63cb5f3c7294b2..9c04b2bbdf39c93617b26d523c0ae9dc740ae1c2 100644 (file)
@@ -1,13 +1,12 @@
 cmake_minimum_required (VERSION 2.6)
 project ("modules")
 
-add_subdirectory(reroute)
 add_subdirectory(ffmpeg)
 add_subdirectory(oal)
 
 if (MSVC)
        add_subdirectory(bluefish)
-endif ()
+endif ()       
 
 add_subdirectory(decklink)
 add_subdirectory(screen)
@@ -20,4 +19,5 @@ if (MSVC)
 endif ()
 
 add_subdirectory(image)
+add_subdirectory(reroute)
 
index 0551dd05684e50389e9a2082867a1b4727b3923b..498d6ae0d11d9d6d156f10ca513b4f22da71bb52 100644 (file)
@@ -3,18 +3,18 @@ project (bluefish)
 
 set(SOURCES
                consumer/bluefish_consumer.cpp
-
                util/blue_velvet.cpp
-
                bluefish.cpp
                StdAfx.cpp
 )
 set(HEADERS
+               interop/BlueDriver_p.h
+               interop/BlueHancUtils.h
+               interop/BlueVelvetC.h
+               interop/BlueVelvetCUtils.h
                consumer/bluefish_consumer.h
-
                util/blue_velvet.h
                util/memory.h
-
                bluefish.h
                StdAfx.h
 )
@@ -26,13 +26,14 @@ include_directories(..)
 include_directories(../..)
 include_directories(${BOOST_INCLUDE_PATH})
 include_directories(${TBB_INCLUDE_PATH})
-include_directories(${BLUEFISH_INCLUDE_PATH})
 include_directories(${RXCPP_INCLUDE_PATH})
 include_directories(${ASMLIB_INCLUDE_PATH})
 
 set_target_properties(bluefish PROPERTIES FOLDER modules)
 source_group(sources ./*)
 source_group(sources\\consumer consumer/*)
+source_group(sources\\interop interop/*)
+source_group(sources\\util util/*)
 
 target_link_libraries(bluefish common core)
 
index 8fb124efeb6eb2d181cacd024b68d5197580448a..5a8278abb5a14f7cf297243f2250fcebbb028f97 100644 (file)
@@ -42,17 +42,13 @@ std::wstring version()
 {
        try
        {
-               blue_initialize();
+               BvcWrapper blue = BvcWrapper();
+               return u16(blue.GetVersion());
        }
        catch(...)
        {
                return L"Not found";
        }
-
-       if(!BlueVelvetVersion)
-               return L"Unknown";
-
-       return u16(BlueVelvetVersion());
 }
 
 std::vector<std::wstring> device_list()
@@ -61,14 +57,15 @@ std::vector<std::wstring> device_list()
 
        try
        {               
-               blue_initialize();
-               
-               auto blue = create_blue();
+               BvcWrapper blue = BvcWrapper();
+               int numCards = 0;
+               blue.Enumerate(numCards);
 
-               for(int n = 1; BLUE_PASS(blue->device_attach(n, FALSE)); ++n)
+               for(int n = 1; n < (numCards+1); n++)
                {                               
-                       devices.push_back(std::wstring(get_card_desc(*blue)) + L" [" + boost::lexical_cast<std::wstring>(n) + L"]");
-                       blue->device_detach();          
+                       blue.Attach(n);
+                       devices.push_back(std::wstring(get_card_desc(blue, n)) + L" [" + boost::lexical_cast<std::wstring>(n) + L"]");  
+                       blue.Detach();
                }
        }
        catch(...){}
@@ -78,21 +75,42 @@ std::vector<std::wstring> device_list()
 
 void init(core::module_dependencies dependencies)
 {
+
+       bool bCanBeConsumer = false;
        try
        {
-               blue_initialize();
+               BvcWrapper blue = BvcWrapper();
+               int numCards = 0;
+               blue.Enumerate(numCards);
+               if (numCards)
+               {
+                       for (int n = 1; n < (numCards + 1); n++)
+                       {
+                               unsigned int value;
+                               blue.Attach(n);
+                               blue.QueryCardProperty32(CARD_FEATURE_STREAM_INFO, value);
+                               if (CARD_FEATURE_GET_SDI_OUTPUT_STREAM_COUNT(value))
+                                       bCanBeConsumer = true;
+
+                               blue.Detach();
+                       }
+               }       
        }
        catch(...){}
 
-       dependencies.consumer_registry->register_consumer_factory(L"Bluefish Consumer", create_consumer, describe_consumer);
-       dependencies.consumer_registry->register_preconfigured_consumer_factory(L"bluefish", create_preconfigured_consumer);
-       dependencies.system_info_provider_repo->register_system_info_provider([](boost::property_tree::wptree& info)
+       if (bCanBeConsumer)
        {
-               info.add(L"system.bluefish.version", version());
-
-               for (auto device : device_list())
-                       info.add(L"system.bluefish.device", device);
-       });
+               dependencies.consumer_registry->register_consumer_factory(L"Bluefish Consumer", create_consumer, describe_consumer);
+               dependencies.consumer_registry->register_preconfigured_consumer_factory(L"bluefish", create_preconfigured_consumer);
+               dependencies.system_info_provider_repo->register_system_info_provider([](boost::property_tree::wptree& info)
+               {
+                       info.add(L"system.bluefish.version", version());
+
+                       for (auto device : device_list())
+                               info.add(L"system.bluefish.device", device);
+               });
+       }
 }
 
-}}
\ No newline at end of file
+}}
+
index a51b9dc80bcd5f39b49fb472fa523bdda3633069..0068f38139efccb4e22dfe311d7ab7e14ceed17f 100644 (file)
 #include <array>
 
 namespace caspar { namespace bluefish { 
-                       
+               
+enum class hardware_downstream_keyer_mode
+{
+       disable = 0,
+       enable = 1,
+};
+
+enum class hardware_downstream_keyer_audio_source
+{
+       SDIVideoInput = 1,
+       VideoOutputChannel = 2
+};
+
+enum class bluefish_hardware_output_channel
+{
+       // ** current Bluefish hardware only support 4224  on channels A and C.
+       hardware_4224_channel_a,
+       hardware_4224_channel_c,
+       hardware_422_channel_a,
+       hardware_422_channel_b,
+       hardware_422_channel_c,
+       hardware_422_channel_d,
+       default_output_channel = hardware_422_channel_a
+};
+
+EBlueVideoChannel get_bluesdk_videochannel_from_streamid(bluefish_hardware_output_channel streamid)
+{
+       /*This function would return the corresponding EBlueVideoChannel from the device output channel*/
+       switch (streamid)
+       {
+               case bluefish_hardware_output_channel::hardware_422_channel_a:  return BLUE_VIDEO_OUTPUT_CHANNEL_A;
+               case bluefish_hardware_output_channel::hardware_4224_channel_a: return BLUE_VIDEO_OUTPUT_CHANNEL_A;
+               case bluefish_hardware_output_channel::hardware_422_channel_b:  return BLUE_VIDEO_OUTPUT_CHANNEL_B;
+               case bluefish_hardware_output_channel::hardware_4224_channel_c: return BLUE_VIDEO_OUTPUT_CHANNEL_C;
+               case bluefish_hardware_output_channel::hardware_422_channel_c:  return BLUE_VIDEO_OUTPUT_CHANNEL_C;
+               case bluefish_hardware_output_channel::hardware_422_channel_d:  return BLUE_VIDEO_OUTPUT_CHANNEL_D;
+               default: return BLUE_VIDEO_OUTPUT_CHANNEL_A;
+       }
+}
+
+bool get_videooutput_channel_routing_info_from_streamid(bluefish_hardware_output_channel streamid,
+       EEpochRoutingElements & channelSrcElement,
+       EEpochRoutingElements & sdioutputDstElement)
+{
+       switch (streamid)
+       {
+       case bluefish_hardware_output_channel::hardware_4224_channel_a: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_A;
+               break;
+       case bluefish_hardware_output_channel::hardware_4224_channel_c: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_C;
+               break;
+       case bluefish_hardware_output_channel::hardware_422_channel_a:  channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_A;
+               break;
+       case bluefish_hardware_output_channel::hardware_422_channel_b:  channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_B;
+               break;
+       case bluefish_hardware_output_channel::hardware_422_channel_c:  channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_C;
+               break;
+       case bluefish_hardware_output_channel::hardware_422_channel_d:  channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD;
+               sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_D;
+               break;
+       default: return false;
+       }
+       return true;
+}
+
 struct bluefish_consumer : boost::noncopyable
 {
-       spl::shared_ptr<CBlueVelvet4>                                           blue_;
+       spl::shared_ptr<BvcWrapper>                                                     blue_;
        const unsigned int                                                                      device_index_;
        const core::video_format_desc                                           format_desc_;
        const core::audio_channel_layout                                        channel_layout_;
@@ -84,6 +152,9 @@ struct bluefish_consumer : boost::noncopyable
        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_;
 public:
        bluefish_consumer(
                        const core::video_format_desc& format_desc,
@@ -92,18 +163,24 @@ public:
                        int device_index,
                        bool embedded_audio,
                        bool key_only,
-                       int channel_index)
+                       hardware_downstream_keyer_mode keyer,
+                       hardware_downstream_keyer_audio_source keyer_audio_source,
+                       int channel_index,
+                       bluefish_hardware_output_channel device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_a)
                : blue_(create_blue(device_index))
                , device_index_(device_index)
                , format_desc_(format_desc)
                , channel_layout_(out_channel_layout)
                , channel_remapper_(in_channel_layout, out_channel_layout)
                , channel_index_(channel_index)
-               , model_name_(get_card_desc(*blue_))
+               , model_name_(get_card_desc(*blue_, device_index))
                , vid_fmt_(get_video_mode(*blue_, format_desc))
                , embedded_audio_(embedded_audio)
+               , hardware_keyer_(keyer)
+               , keyer_audio_source_(keyer_audio_source)
                , key_only_(key_only)
                , executor_(print())
+               , device_output_channel_(device_output_channel)
        {
                executor_.set_capacity(1);
                presentation_delay_millis_ = 0;
@@ -113,23 +190,20 @@ public:
                graph_->set_color("frame-time", diagnostics::color(0.5f, 1.0f, 0.2f));
                graph_->set_text(print());
                diagnostics::register_graph(graph_);
-                       
-               //Setting output Video mode
+
+               // Specify the video channel
+               setup_hardware_output_channel();
+
+               // Setting output Video mode
                if(BLUE_FAIL(set_card_property(blue_, VIDEO_MODE, vid_fmt_))) 
                        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set videomode."));
 
-               //Select Update Mode for output
+               // Select Update Mode for output
                if(BLUE_FAIL(set_card_property(blue_, VIDEO_UPDATE_TYPE, UPD_FMT_FRAME))) 
                        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set update type."));
        
                disable_video_output();
-
-               //Enable dual link output
-               if(BLUE_FAIL(set_card_property(blue_, VIDEO_DUAL_LINK_OUTPUT, 1)))
-                       CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to enable dual link."));
-
-               if(BLUE_FAIL(set_card_property(blue_, 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."));
+               setup_hardware_output_channel_routing();
                        
                //Select output memory format
                if(BLUE_FAIL(set_card_property(blue_, VIDEO_MEMORY_FORMAT, MEM_FMT_ARGB_PC))) 
@@ -143,10 +217,7 @@ public:
                if(BLUE_FAIL(set_card_property(blue_, VIDEO_RGB_DATA_RANGE, CGR_RANGE))) 
                        CASPAR_LOG(warning) << print() << L" Failed to set RGB data range to CGR.";     
                
-               if(BLUE_FAIL(set_card_property(blue_, VIDEO_PREDEFINED_COLOR_MATRIX, vid_fmt_ == VID_FMT_PAL ? MATRIX_601_CGR : MATRIX_709_CGR)))
-                       CASPAR_LOG(warning) << print() << L" Failed to set colormatrix to " << (vid_fmt_ == VID_FMT_PAL ? L"601 CGR" : L"709 CGR") << L".";
-
-               if(!embedded_audio_)
+               if(!embedded_audio_ || (hardware_keyer_ == hardware_downstream_keyer_mode::enable && keyer_audio_source_ == hardware_downstream_keyer_audio_source::VideoOutputChannel) )
                {
                        if(BLUE_FAIL(set_card_property(blue_, EMBEDEDDED_AUDIO_OUTPUT, 0))) 
                                CASPAR_LOG(warning) << TEXT("BLUECARD ERROR: Failed to disable embedded audio.");                       
@@ -170,19 +241,13 @@ public:
                                CASPAR_LOG(warning) << print() << TEXT(" Failed to enable embedded audio.");                    
                        CASPAR_LOG(info) << print() << TEXT(" Enabled embedded-audio.");
                }
-               
-               if (blue_->has_output_key()) 
-               {
-                       int dummy = TRUE; int v4444 = FALSE; int invert = FALSE; int white = FALSE;
-                       blue_->set_output_key(dummy, v4444, invert, white);
-               }
 
-               if(blue_->GetHDCardType(device_index_) != CRD_HD_INVALID) 
-                       blue_->Set_DownConverterSignalType(vid_fmt_ == VID_FMT_PAL ? SD_SDI : HD_SDI);  
-       
                if(BLUE_FAIL(set_card_property(blue_, VIDEO_OUTPUT_ENGINE, VIDEO_ENGINE_FRAMESTORE))) 
-                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set video engine."); 
-               
+                       CASPAR_LOG(warning) << print() << TEXT(" Failed to set video engine.");
+
+               if (is_epoch_card((*blue_)))
+                       setup_hardware_downstream_keyer(hardware_keyer_, keyer_audio_source_);
+
                enable_video_output();
                                                
                int n = 0;
@@ -196,7 +261,7 @@ public:
                        executor_.invoke([&]
                        {
                                disable_video_output();
-                               blue_->device_detach();         
+                               blue_->Detach();                
                        });
                }
                catch(...)
@@ -204,17 +269,159 @@ public:
                        CASPAR_LOG_CURRENT_EXCEPTION();
                }
        }
-       
+
+       void setup_hardware_output_channel()
+       {
+               // this function would be used to setup the logic video channel in the bluefish hardware
+               EBlueVideoChannel outVidChannel = get_bluesdk_videochannel_from_streamid(device_output_channel_);
+               if (is_epoch_card((*blue_)))
+               {
+                       if (outVidChannel != BLUE_VIDEOCHANNEL_INVALID)
+                       {
+                               if (BLUE_FAIL(set_card_property(blue_, DEFAULT_VIDEO_OUTPUT_CHANNEL, outVidChannel)))
+                                       CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to set video stream."));
+                       }
+               }
+       }
+
+       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 srcElement = (EEpochRoutingElements)0;
+                       EEpochRoutingElements dstElement = (EEpochRoutingElements)0;
+                       get_videooutput_channel_routing_info_from_streamid(device_output_channel_, srcElement, dstElement);
+                       bool duallink_4224_enabled = false;
+
+                       if (device_output_channel_ == bluefish_hardware_output_channel::hardware_4224_channel_a || device_output_channel_ == bluefish_hardware_output_channel::hardware_4224_channel_c)
+                               duallink_4224_enabled = true;
+
+                       // Enable/Disable dual link output
+                       if (BLUE_FAIL(set_card_property(blue_, 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(set_card_property(blue_, 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(srcElement, dstElement, BLUE_CONNECTOR_PROP_SINGLE_LINK);
+                               if (BLUE_FAIL(set_card_property(blue_, 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(set_card_property(blue_, 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(set_card_property(blue_, 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(set_card_property(blue_, 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(set_card_property(blue_, 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(set_card_property(blue_, 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)
+       {
+               ULONG keyer_control_value = 0, card_feature_value = 0;
+               ULONG card_connector_value = 0;
+               unsigned int nOutputStreams = 0;
+               unsigned int nInputStreams = 0;
+               unsigned int nInputSDIConnector = 0;
+               unsigned int nOutputSDIConnector = 0;
+               if (BLUE_OK(get_card_property(blue_, 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(get_card_property(blue_, 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_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::enable)
+               {
+                       ULONG invalidVideoModeFlag = 0;
+                       ULONG inputVideoSignal = 0;
+                       if (BLUE_FAIL(get_card_property(blue_, INVALID_VIDEO_MODE_FLAG, invalidVideoModeFlag)))
+                               CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to get invalid video mode flag"));
+
+                       keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(keyer_control_value);
+                       if (BLUE_FAIL(get_card_property(blue_, 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(set_card_property(blue_, 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::enable))
+                       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(set_card_property(blue_, VIDEO_ONBOARD_KEYER, keyer_control_value)))
+                       CASPAR_LOG(error) << print() << TEXT(" Failed to set keyer control.");
+       }
+
        void enable_video_output()
        {
-               if(!BLUE_PASS(set_card_property(blue_, VIDEO_BLACKGENERATOR, 0)))
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_BLACKGENERATOR, 0)))
                        CASPAR_LOG(error) << print() << TEXT(" Failed to disable video output.");       
        }
 
        void disable_video_output()
        {
-               blue_->video_playback_stop(0,0);
-               if(!BLUE_PASS(set_card_property(blue_, VIDEO_BLACKGENERATOR, 1)))
+               blue_->VideoPlaybackStop(0,0);
+               if(BLUE_FAIL(set_card_property(blue_, VIDEO_BLACKGENERATOR, 1)))
                        CASPAR_LOG(error)<< print() << TEXT(" Failed to disable video output.");                
        }
        
@@ -243,7 +450,7 @@ public:
 
                sync_timer_.restart();
                unsigned long n_field = 0;
-               blue_->wait_output_video_synch(UPD_FMT_FRAME, n_field);
+               blue_->WaitVideoOutputSync(UPD_FMT_FRAME, n_field);
                graph_->set_value("sync-time", sync_timer_.elapsed()*format_desc_.fps*0.5);
                
                frame_timer_.restart();         
@@ -277,27 +484,27 @@ public:
                                                static_cast<int>(frame.audio_data().size()/channel_layout_.num_channels), 
                                                static_cast<int>(channel_layout_.num_channels));
                                                                
-                       blue_->system_buffer_write_async(const_cast<uint8_t*>(reserved_frames_.front()->image_data()), 
-                                                                                       static_cast<unsigned long>(reserved_frames_.front()->image_size()), 
-                                                                                       nullptr
-                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));
+                       blue_->SystemBufferWrite(const_cast<uint8_t*>(reserved_frames_.front()->image_data()), 
+                                                                                       static_cast<unsigned long>(reserved_frames_.front()->image_size()),  
+                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE)
+                                                                                       0);
 
-                       blue_->system_buffer_write_async(reserved_frames_.front()->hanc_data(),
-                                                                                       static_cast<unsigned long>(reserved_frames_.front()->hanc_size()), 
-                                                                                       nullptr,                 
-                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_HANC));
+                       blue_->SystemBufferWrite(reserved_frames_.front()->hanc_data(),
+                                                                                       static_cast<unsigned long>(reserved_frames_.front()->hanc_size()),
+                                                                                       BlueImage_HANC_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_HANC),
+                                                                                       0);
 
-                       if(BLUE_FAIL(blue_->render_buffer_update(BlueBuffer_Image_HANC(reserved_frames_.front()->id()))))
+                       if(BLUE_FAIL(blue_->RenderBufferUpdate(BlueBuffer_Image_HANC(reserved_frames_.front()->id()))))
                                CASPAR_LOG(warning) << print() << TEXT(" render_buffer_update failed.");
                }
                else
                {
-                       blue_->system_buffer_write_async(const_cast<uint8_t*>(reserved_frames_.front()->image_data()),
+                       blue_->SystemBufferWrite(const_cast<uint8_t*>(reserved_frames_.front()->image_data()),
                                                                                        static_cast<unsigned long>(reserved_frames_.front()->image_size()), 
-                                                                                       nullptr,                 
-                                                                                       BlueImage_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE));
+                                                                                       BlueImage_DMABuffer(reserved_frames_.front()->id(), BLUE_DATA_IMAGE),
+                                                                                       0);
                        
-                       if(BLUE_FAIL(blue_->render_buffer_update(BlueBuffer_Image(reserved_frames_.front()->id()))))
+                       if(BLUE_FAIL(blue_->RenderBufferUpdate(BlueBuffer_Image(reserved_frames_.front()->id()))))
                                CASPAR_LOG(warning) << print() << TEXT(" render_buffer_update failed.");
                }
 
@@ -330,10 +537,9 @@ public:
                hanc_stream_info.hanc_data_ptr    = hanc_data;
                hanc_stream_info.video_mode               = vid_fmt_;           
                
-               if (!is_epoch_card(*blue_))
-                       encode_hanc_frame(&hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);  
-               else
-                       encode_hanc_frame_ex(blue_->has_video_cardtype(), &hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);
+               int cardType = CRD_INVALID;
+               blue_->QueryCardType(cardType, device_index_);
+               blue_->EncodeHancFrameEx(cardType, &hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);
        }
        
        std::wstring print() const
@@ -350,25 +556,38 @@ public:
 
 struct bluefish_consumer_proxy : public core::frame_consumer
 {
-       core::monitor::subject                          monitor_subject_;
+       core::monitor::subject                                  monitor_subject_;
 
-       std::unique_ptr<bluefish_consumer>      consumer_;
-       const int                                                       device_index_;
-       const bool                                                      embedded_audio_;
-       const bool                                                      key_only_;
+       std::unique_ptr<bluefish_consumer>              consumer_;
+       const int                                                               device_index_;
+       const bool                                                              embedded_audio_;
+       const bool                                                              key_only_;
 
-       std::vector<int>                                        audio_cadence_;
-       core::video_format_desc                         format_desc_;
-       core::audio_channel_layout                      in_channel_layout_              = core::audio_channel_layout::invalid();
-       core::audio_channel_layout                      out_channel_layout_;
+       std::vector<int>                                                audio_cadence_;
+       core::video_format_desc                                 format_desc_;
+       core::audio_channel_layout                              in_channel_layout_              = core::audio_channel_layout::invalid();
+       core::audio_channel_layout                              out_channel_layout_;
+       hardware_downstream_keyer_mode                  hardware_keyer_;
+       hardware_downstream_keyer_audio_source  hardware_keyer_audio_source_;
+       bluefish_hardware_output_channel                hardware_output_channel_;
 
 public:
 
-       bluefish_consumer_proxy(int device_index, bool embedded_audio, bool key_only, const core::audio_channel_layout& out_channel_layout)
+       bluefish_consumer_proxy(int device_index, 
+                                                       bool embedded_audio, 
+                                                       bool key_only, 
+                                                       hardware_downstream_keyer_mode keyer,
+                                                       hardware_downstream_keyer_audio_source keyer_audio_source,
+                                                       const core::audio_channel_layout& out_channel_layout,
+                                                       bluefish_hardware_output_channel hardware_output_channel)
+
                : device_index_(device_index)
                , embedded_audio_(embedded_audio)
                , key_only_(key_only)
+               , hardware_keyer_(keyer)
+               , hardware_keyer_audio_source_(keyer_audio_source)
                , out_channel_layout_(out_channel_layout)
+               , hardware_output_channel_(hardware_output_channel)
        {
        }
        
@@ -384,7 +603,16 @@ public:
                        out_channel_layout_ = in_channel_layout_;
 
                consumer_.reset();
-               consumer_.reset(new bluefish_consumer(format_desc, in_channel_layout_, out_channel_layout_, device_index_, embedded_audio_, key_only_, channel_index));
+               consumer_.reset(new bluefish_consumer(  format_desc, 
+                                                                                               in_channel_layout_, 
+                                                                                               out_channel_layout_, 
+                                                                                               device_index_, 
+                                                                                               embedded_audio_, 
+                                                                                               key_only_, 
+                                                                                               hardware_keyer_,
+                                                                                               hardware_keyer_audio_source_, 
+                                                                                               channel_index,
+                                                                                               hardware_output_channel_));
        }
        
        std::future<bool> send(core::const_frame frame) override
@@ -451,16 +679,34 @@ void describe_consumer(core::help_sink& sink, const core::help_repository& repo)
                ->text(L"channel. This is useful when you have two SDI video cards, and neither has native support ")
                ->text(L"for separate fill/key output");
        sink.para()->text(L"Specify ")->code(L"channel_layout")->text(L" to output a different audio channel layout than the channel uses.");
+       sink.para()->text(L"Specify ")->code(L"BF_4224_CHANNELA")->text(L" to use channel A on the card to  be configured to output "
+               L"4:2:2:4 with fill and key HD-SDI output's A and B on the card.\n"
+               L"This is the default option\n");
+       sink.para()->text(L"Specify ")->code(L"BF_4224_CHANNELC")->text(L" to use channel C on the card to  be configured to output "
+               L" 4:2:2:4 with fill and key  HD-SDI output's C and D on the card\n"
+               L" Channel C 4:2:2:4 support is only available on 4 output variant of Supernova  and SupernovaS+ card\n");
+
+       sink.para()->text(L"Specify ")->code(L"ENABLE_KEYER")->text(L" to enable use of hardware keyer on the bluefish board.\n"
+               L"\t\t\tUsing this option hardware keyer would key using \n "
+               L"\t\t\tthe video input on the SDI as background layer \n"
+               L"\t\t\tand graphics Generated by CasparCG as foreground layer");
+       sink.para()->text(L"Specify ")->code(L"DISABLE_KEYER")->text(L" this option to disable hardware keyer on the bluefish board");
+       sink.para()->text(L"Specify ")->code(L"KEYER_AUDIO_SOURCE_SDIINPUT")->text(L" to enable SDI embedded audio to be transparently passed through the keyer to the SDI output\n");
+       sink.para()->text(L"Specify ")->code(L"KEYER_AUDIO_SOURCE_OUTPUT_CHANNEL")->text(L" to enable keyer to pass the audio provided by CasparCG to the SDI output\n");
+
        sink.para()->text(L"Examples:");
        sink.example(L">> ADD 1 BLUEFISH", L"uses the default device_index of 1.");
        sink.example(L">> ADD 1 BLUEFISH 2", L"for device_index 2.");
        sink.example(
                L">> ADD 1 BLUEFISH 1 EMBEDDED_AUDIO\n"
                L">> ADD 1 BLUEFISH 2 KEY_ONLY", L"uses device with index 1 as fill output with audio and device with index 2 as key output.");
+
 }
 
-spl::shared_ptr<core::frame_consumer> create_consumer(
-               const std::vector<std::wstring>& params, core::interaction_sink*, std::vector<spl::shared_ptr<core::video_channel>> channels)
+
+spl::shared_ptr<core::frame_consumer> create_consumer( const std::vector<std::wstring>& params,
+                                                                                                               core::interaction_sink*,
+                                                                                                               std::vector<spl::shared_ptr<core::video_channel>> channels)
 {
        if(params.size() < 1 || !boost::iequals(params.at(0), L"BLUEFISH"))
                return core::frame_consumer::empty();
@@ -470,6 +716,7 @@ spl::shared_ptr<core::frame_consumer> create_consumer(
        const auto embedded_audio       = contains_param(       L"EMBEDDED_AUDIO",      params);
        const auto key_only                     = contains_param(       L"KEY_ONLY",            params);
        const auto channel_layout       = get_param(            L"CHANNEL_LAYOUT",      params);
+       const auto device_stream        = contains_param(       L"SDI-STREAM",          params);
 
        auto layout = core::audio_channel_layout::invalid();
 
@@ -482,17 +729,49 @@ spl::shared_ptr<core::frame_consumer> create_consumer(
 
                layout = *found_layout;
        }
-
-       return spl::make_shared<bluefish_consumer_proxy>(device_index, embedded_audio, key_only, layout);
+       bluefish_hardware_output_channel device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_a;
+
+       if (contains_param(L"BLUE_4224_CHANNELA", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_a;
+       else if (contains_param(L"BLUE_4224_CHANNELC", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_c;
+       else if (contains_param(L"BLUE_422_CHANNELA", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_a;
+       else if (contains_param(L"BLUE_422_CHANNELB", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_b;
+       else if (contains_param(L"BLUE_422_CHANNELC", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_c;
+       else if (contains_param(L"BLUE_422_CHANNELD", params))
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_d;
+
+       hardware_downstream_keyer_mode keyer = hardware_downstream_keyer_mode::disable;
+
+       if (contains_param(L"KEYER_DISABLED", params))
+               keyer = hardware_downstream_keyer_mode::disable;
+       else if (contains_param(L"KEYER_ENABLED", params))
+               keyer = hardware_downstream_keyer_mode::enable;
+
+       hardware_downstream_keyer_audio_source keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;
+       if (contains_param(L"KEYER_AUDIO_SOURCE_SDIINPUT", params))
+               keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput;
+       else
+       if (contains_param(L"KEYER_AUDIO_SOURCE_OUTPUT_CHANNEL", params))
+               keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;
+
+       return spl::make_shared<bluefish_consumer_proxy>(device_index, embedded_audio, key_only, keyer, keyer_audio_source, layout, device_output_channel);
 }
 
 spl::shared_ptr<core::frame_consumer> create_preconfigured_consumer(
-               const boost::property_tree::wptree& ptree, core::interaction_sink*, std::vector<spl::shared_ptr<core::video_channel>> channels)
-{
+                                                                                       const boost::property_tree::wptree& ptree, core::interaction_sink*,
+                                                                                       std::vector<spl::shared_ptr<core::video_channel>> channels)
+{      
        const auto device_index         = ptree.get(                                            L"device",                      1);
        const auto embedded_audio       = ptree.get(                                            L"embedded-audio",      false);
        const auto key_only                     = ptree.get(                                            L"key-only",            false);
        const auto channel_layout       = ptree.get_optional<std::wstring>(     L"channel-layout");
+       const auto hardware_keyer_value = ptree.get(L"hardware-keyer", L"disabled");
+       const auto keyer_audio_source_value = ptree.get(L"hardware-keyer-audio-source", L"videooutputchannel");
+       const auto device_stream = ptree.get(L"sdi-stream", L"blue_4224_channela");
 
        auto layout = core::audio_channel_layout::invalid();
 
@@ -508,7 +787,38 @@ spl::shared_ptr<core::frame_consumer> create_preconfigured_consumer(
                layout = *found_layout;
        }
 
-       return spl::make_shared<bluefish_consumer_proxy>(device_index, embedded_audio, key_only, layout);
+       bluefish_hardware_output_channel device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_a;
+       if (device_stream == L"blue_4224_channela")
+               device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_a;
+       else if (device_stream == L"blue_4224_channelc")
+               device_output_channel = bluefish_hardware_output_channel::hardware_4224_channel_c;
+       else if (device_stream == L"blue_422_channela")
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_a;
+       else if (device_stream == L"blue_422_channelb")
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_b;
+       else if (device_stream == L"blue_422_channelc")
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_c;
+       else if (device_stream == L"blue_422_channeld")
+               device_output_channel = bluefish_hardware_output_channel::hardware_422_channel_d;
+
+       hardware_downstream_keyer_mode keyer_mode = hardware_downstream_keyer_mode::disable;
+       if (hardware_keyer_value == L"disabled")
+       {
+               keyer_mode = hardware_downstream_keyer_mode::disable;
+       }
+       else if (hardware_keyer_value == L"enabled")
+       {
+               keyer_mode = hardware_downstream_keyer_mode::enable;
+       }
+
+       hardware_downstream_keyer_audio_source keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;
+       if (keyer_audio_source_value == L"videooutputchannel")
+               keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;
+       else
+               if (keyer_audio_source_value == L"sdivideoinput")
+                       keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput;
+
+       return spl::make_shared<bluefish_consumer_proxy>(device_index, embedded_audio, key_only, keyer_mode, keyer_audio_source, layout, device_output_channel);
 }
 
 }}
\ No newline at end of file
index bcdc48bdd93f7809a872a1e351c27313a6c710b1..dab1c4e95466a90d3ff331f7a122504b39e0ccd0 100644 (file)
 namespace caspar { namespace bluefish {
 
 void describe_consumer(core::help_sink& sink, const core::help_repository& repo);
-spl::shared_ptr<core::frame_consumer> create_consumer(
-               const std::vector<std::wstring>& params, core::interaction_sink*,
-               std::vector<spl::shared_ptr<core::video_channel>> channels);
-spl::shared_ptr<core::frame_consumer> create_preconfigured_consumer(
-               const boost::property_tree::wptree& ptree, core::interaction_sink*,
-               std::vector<spl::shared_ptr<core::video_channel>> channels);
 
-}}
+
+spl::shared_ptr<core::frame_consumer> create_consumer( const std::vector<std::wstring>& params, 
+                                                                                                               core::interaction_sink*,
+                                                                                                               std::vector<spl::shared_ptr<core::video_channel>> channels);
+
+
+spl::shared_ptr<core::frame_consumer> create_preconfigured_consumer(
+                                                                                                               const boost::property_tree::wptree& ptree, core::interaction_sink*,
+                                                                                                               std::vector<spl::shared_ptr<core::video_channel>> channels);
+}}
\ No newline at end of file
index e1802c6d53a1108e62306d6c5fd242e99e055fa4..a8384f349a2af4d2db79d3e87bcd695604faf353 100644 (file)
 */
 
 #include "../StdAfx.h"
-
 #include "blue_velvet.h"
+#include <common/utf.h>        
+#include <core/video_format.h>
+#include <bluefish/interop/BlueVelvetCUtils.h>
 
-#include <common/utf.h>
+#if defined(__APPLE__)
+       #include <dlfcn.h>
+#endif
 
-#include <core/video_format.h>
+#if defined(_WIN32)
+       #define GET_PROCADDR_FOR_FUNC(name, module) { name = (pFunc_##name)GetProcAddress(module, #name); if(!name) { return false; } }
+#elif defined(__APPLE__)
+       #define GET_PROCADDR_FOR_FUNC(name, module) { name = (pFunc_##name)dlsym(module, #name); if(!name) { return false; } }
+#endif
 
 namespace caspar { namespace bluefish {
-       
-CBlueVelvet4* (*BlueVelvetFactory4)() = nullptr;
-void (*BlueVelvetDestroy)(CBlueVelvet4* pObj) = nullptr;
-const char*    (*BlueVelvetVersion)() = nullptr;
-BLUE_UINT32 (*encode_hanc_frame)(struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr,BLUE_UINT32 no_audio_ch,BLUE_UINT32 no_audio_samples,BLUE_UINT32 nTypeOfSample,BLUE_UINT32 emb_audio_flag) = nullptr;
-BLUE_UINT32 (*encode_hanc_frame_ex)(BLUE_UINT32 card_type, struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr, BLUE_UINT32 no_audio_ch,    BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag) = nullptr;
 
-void blue_velvet_initialize()
-{
-#ifdef _DEBUG
-       std::string module_str = "BlueVelvet64_d.dll";
-#else
-       std::string module_str = "BlueVelvet64.dll";
+       BvcWrapper::BvcWrapper()
+       {
+               bvc = nullptr;
+               hModule = nullptr;
+               InitFunctionsPointers();
+               if (bfcFactory)
+                       bvc = bfcFactory();
+       }
+
+       BvcWrapper::~BvcWrapper()
+       {
+               if (bvc)
+                       bfcDestroy(bvc);
+               if (hModule)
+               {
+#if defined(_WIN32)
+                       FreeLibrary(hModule);
+#elif defined(__APPLE__)
+                       dlclose(hModule);
 #endif
+               }
+       }
 
-       auto module = LoadLibrary(u16(module_str).c_str());
-       if(!module)
-               LoadLibrary(u16(std::string(getenv("SystemDrive")) + "\\Program Files\\Bluefish444\\Driver\\" + module_str).c_str());
-       if(!module)
-               LoadLibrary(u16(std::string(getenv("SystemDrive")) + "\\Program Files (x86)\\BlueFish444\\Driver\\" + module_str).c_str());
-       if(!module)
-               CASPAR_THROW_EXCEPTION(file_not_found() << msg_info("Could not find BlueVelvet3.dll. Required drivers are not installed."));
-       static std::shared_ptr<void> lib(module, FreeLibrary);
-       BlueVelvetFactory4 = reinterpret_cast<decltype(BlueVelvetFactory4)>(GetProcAddress(module, "BlueVelvetFactory4"));
-       BlueVelvetDestroy  = reinterpret_cast<decltype(BlueVelvetDestroy)>(GetProcAddress(module, "BlueVelvetDestroy"));
-       BlueVelvetVersion  = reinterpret_cast<decltype(BlueVelvetVersion)>(GetProcAddress(module, "BlueVelvetVersion"));
-}
+       bool BvcWrapper::InitFunctionsPointers()
+       {
+               bool bRes = false;
 
-void blue_hanc_initialize()
-{
+#if defined(_WIN32)
 #ifdef _DEBUG
-       std::string module_str = "BlueHancUtils64_d.dll";
+               hModule = LoadLibraryExA("BlueVelvetC64_d.dll", NULL, 0);
 #else
-       std::string module_str = "BlueHancUtils64.dll";
+               hModule = LoadLibraryExA("BlueVelvetC64.dll", NULL, 0);
 #endif
-       
-       auto module = LoadLibrary(u16(module_str).c_str());
-       if(!module)
-               LoadLibrary(u16(std::string(getenv("SystemDrive")) + "\\Program Files\\Bluefish444\\Driver\\" + module_str).c_str());
-       if(!module)
-               LoadLibrary(u16(std::string(getenv("SystemDrive")) + "\\Program Files (x86)\\BlueFish444\\Driver\\" + module_str).c_str());
-       if(!module)
-               CASPAR_THROW_EXCEPTION(file_not_found() << msg_info("Could not find BlueHancUtils.dll. Required drivers are not installed."));
-       static std::shared_ptr<void> lib(module, FreeLibrary);
-       encode_hanc_frame        = reinterpret_cast<decltype(encode_hanc_frame)>(GetProcAddress(module, "encode_hanc_frame"));
-       encode_hanc_frame_ex = reinterpret_cast<decltype(encode_hanc_frame_ex)>(GetProcAddress(module, "encode_hanc_frame_ex"));
-}
+               
+#elif defined(__APPLE__)
+               // Look for the framework and load it accordingly.
+               char* libraryPath("/Library/Frameworks/BlueVelvetC.framework");         // full path may not be required, OSX might check in /l/f by default - MUST TEST!
+               hModule = dlopen(libraryPath, RTLD_NOW);
+#endif
+               
+               if (hModule)
+               {
+                       GET_PROCADDR_FOR_FUNC(bfcGetVersion, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcFactory, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcDestroy, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcEnumerate, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcQueryCardType, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcAttach, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcDetach, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty32, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty64, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcSetCardProperty32, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcSetCardProperty64, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetCardSerialNumber, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetCardFwVersion, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcWaitVideoSyncAsync, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcWaitVideoInputSync, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcWaitVideoOutputSync, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVideoOutputCurrentFieldCount, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVideoInputCurrentFieldCount, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStart, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStop, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStart, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStop, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackAllocate, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackPresent, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackRelease, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetCaptureVideoFrameInfoEx, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcRenderBufferCapture, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcRenderBufferUpdate, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetRenderBufferCount, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcEncodeHancFrameEx, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcDecodeHancFrameEx, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcSystemBufferReadAsync, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcSystemBufferWriteAsync, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetBytesForGroupPixels, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetPixelsPerLine, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetLinesPerFrame, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetBytesPerLine, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetBytesPerFrame, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetGoldenValue, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVBILines, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVANCGoldenValue, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVANCLineBytes, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetVANCLineCount, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcGetWindowsDriverHandle, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForCardType, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForBlueProductId, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForVideoMode, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForMemoryFormat, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetMR2Routing, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsSetMR2Routing, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioOutputRouting, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsSetAudioOutputRouting, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoModeProgressive, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoMode1001Framerate, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetFpsForVideoMode, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetVideoModeForFrameInfo, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetFrameInfoForVideoMode, hModule);
+                       GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioSamplesPerFrame, hModule);
+
+                       bRes = true;
+               }
+
+               return bRes;
+       }
+
+       bool BvcWrapper::IsBvcValid()
+       {
+               if (bvc)
+                       return true;
+               else
+                       return false;
+       }
+
+       const char * BvcWrapper::GetVersion()
+       {
+               return bfcGetVersion();
+       }
+
+       BLUE_UINT32 BvcWrapper::Attach(int iDeviceId)
+       {
+               return bfcAttach(bvc, iDeviceId);
+       }
+
+       BLUE_UINT32 BvcWrapper::Detach()
+       {
+               return bfcDetach(bvc);
+       }
+
+       BLUE_UINT32 BvcWrapper::QueryCardProperty32(const int iProperty, unsigned int & nValue)
+       {
+               if (bvc)
+                       return (BLUE_UINT32)bfcQueryCardProperty32(bvc, iProperty, nValue);
+               else
+                       return 0;
+       }
+
+       BLUE_UINT32 BvcWrapper::SetCardProperty32(const int iProperty, const unsigned int nValue)
+       {
+               return bfcSetCardProperty32(bvc, iProperty, nValue);
+       }
+
+       BLUE_UINT32 BvcWrapper::Enumerate(int & iDevices)
+       {
+               return bfcEnumerate(bvc, iDevices);
+       }
+
+       BLUE_UINT32 BvcWrapper::QueryCardType(int & iCardType, int iDeviceID)
+       {
+               return bfcQueryCardType(bvc, iCardType, iDeviceID);
+       }
+
+       BLUE_UINT32 BvcWrapper::SystemBufferWrite(unsigned char * pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset)
+       {
+               return bfcSystemBufferWriteAsync(bvc, pPixels, ulSize, nullptr, ulBufferID, ulOffset);
+       }
+
+       BLUE_UINT32 BvcWrapper::SystemBufferRead(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset)
+       {
+               return bfcSystemBufferReadAsync(bvc, pPixels, ulSize, nullptr, ulBufferID, ulOffset);
+       }
+
+       BLUE_UINT32 BvcWrapper::VideoPlaybackStop(int iWait, int iFlush)
+       {
+               return bfcVideoPlaybackStop(bvc, iWait, iFlush);
+       }
+
+       BLUE_UINT32 BvcWrapper::WaitVideoOutputSync(unsigned long ulUpdateType, unsigned long & ulFieldCount)
+       {
+               return bfcWaitVideoOutputSync(bvc, ulUpdateType, ulFieldCount);
+       }
+
+       BLUE_UINT32 BvcWrapper::WaitVideoInputSync(unsigned long ulUpdateType, unsigned long & ulFieldCount)
+       {
+               return bfcWaitVideoInputSync(bvc, ulUpdateType, ulFieldCount);
+       }
+
+       BLUE_UINT32 BvcWrapper::RenderBufferUpdate( unsigned long ulBufferID)
+       {
+               return bfcRenderBufferUpdate(bvc, ulBufferID);
+       }
+
+       BLUE_UINT32 BvcWrapper::RenderBufferCapture(unsigned long ulBufferID)
+       {
+               return bfcRenderBufferCapture(bvc, ulBufferID);
+       }
+
+       BLUE_UINT32 BvcWrapper::EncodeHancFrameEx(unsigned int nCardType, hanc_stream_info_struct * pHancEncodeInfo, void * pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags)
+       {
+               return bfcEncodeHancFrameEx(bvc, CRD_BLUE_NEUTRON, pHancEncodeInfo, pAudioBuffer, nAudioChannels, nAudioSamples, nSampleType, nAudioFlags);
+       }
+
+       BLUE_UINT32 BvcWrapper::DecodeHancFrameEx(unsigned int nCardType, unsigned int * pHancBuffer, hanc_decode_struct * pHancDecodeInfo)
+       {
+               return bfcDecodeHancFrameEx(bvc, CRD_BLUE_NEUTRON, pHancBuffer, pHancDecodeInfo);
+       }
+
+       BLUE_UINT32 BvcWrapper::GetFrameInfoForVideoVode(const unsigned int nVideoMode, unsigned int&  nWidth, unsigned int& nHeight, unsigned int& nRate, unsigned int& bIs1001, unsigned int& bIsProgressive)
+       {
+               return bfcUtilsGetFrameInfoForVideoMode(nVideoMode, nWidth, nHeight, nRate, bIs1001, bIsProgressive);
+       }
+
+       BLUE_UINT32 BvcWrapper::GetBytesPerFrame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame)
+       {
+               return bfcGetBytesPerFrame(nVideoMode, nMemoryFormat, nUpdateMethod, nBytesPerFrame);
+       }
 
-void blue_initialize()
-{
-       blue_hanc_initialize();
-       blue_velvet_initialize();
-}
 
 EVideoMode vid_fmt_from_video_format(const core::video_format& fmt) 
 {
@@ -112,100 +276,274 @@ EVideoMode vid_fmt_from_video_format(const core::video_format& fmt)
        }
 }
 
-bool is_epoch_card(CBlueVelvet4& blue)
+bool is_epoch_card(BvcWrapper& blue)
 {
-       switch(blue.has_video_cardtype())
-       {
-       case CRD_BLUE_EPOCH_HORIZON:
-       case CRD_BLUE_EPOCH_CORE:
-       case CRD_BLUE_EPOCH_ULTRA:
-       case CRD_BLUE_EPOCH_2K_HORIZON:
-       case CRD_BLUE_EPOCH_2K_CORE:
-       case CRD_BLUE_EPOCH_2K_ULTRA:
-       case CRD_BLUE_CREATE_HD:
-       case CRD_BLUE_CREATE_2K:
-       case CRD_BLUE_CREATE_2K_ULTRA:
-       case CRD_BLUE_SUPER_NOVA:
+       int iDeviceID = 1;
+       int iCardType = 0;
+       blue.QueryCardType(iCardType, iDeviceID);
+
+       switch(iCardType)
+       {
+               case CRD_BLUE_EPOCH_HORIZON:
+               case CRD_BLUE_EPOCH_CORE:
+               case CRD_BLUE_EPOCH_ULTRA:
+               case CRD_BLUE_EPOCH_2K_HORIZON:
+               case CRD_BLUE_EPOCH_2K_CORE:
+               case CRD_BLUE_EPOCH_2K_ULTRA:
+               case CRD_BLUE_CREATE_HD:
+               case CRD_BLUE_CREATE_2K:
+               case CRD_BLUE_CREATE_2K_ULTRA:
+               case CRD_BLUE_SUPER_NOVA:
+               case CRD_BLUE_SUPER_NOVA_S_PLUS:
+               case CRD_BLUE_NEUTRON:
+               case CRD_BLUE_EPOCH_CG:
                return true;
        default:
                return false;
        }
 }
 
-std::wstring get_card_desc(CBlueVelvet4& blue)
+bool is_epoch_neutron_1i2o_card(BvcWrapper& blue)
 {
-       switch(blue.has_video_cardtype()) 
-       {
-       case CRD_BLUEDEEP_LT:                           return L"Deepblue LT";// D64 Lite
-       case CRD_BLUEDEEP_SD:                           return L"Iridium SD";// Iridium SD
-       case CRD_BLUEDEEP_AV:                           return L"Iridium AV";// Iridium AV
-       case CRD_BLUEDEEP_IO:                           return L"Deepblue IO";// D64 Full
-       case CRD_BLUEWILD_AV:                           return L"Wildblue AV";// D64 AV
-       case CRD_IRIDIUM_HD:                            return L"Iridium HD";// * Iridium HD
-       case CRD_BLUEWILD_RT:                           return L"Wildblue RT";// D64 RT
-       case CRD_BLUEWILD_HD:                           return L"Wildblue HD";// * BadAss G2
-       case CRD_REDDEVIL:                                      return L"Iridium Full";// Iridium Full
-       case CRD_BLUEDEEP_HD:   
-       case CRD_BLUEDEEP_HDS:                          return L"Reserved for \"BasAss G2";// * BadAss G2 variant, proposed, reserved
-       case CRD_BLUE_ENVY:                                     return L"Blue Envy"; // Mini Din 
-       case CRD_BLUE_PRIDE:                            return L"Blue Pride";//Mini Din Output 
-       case CRD_BLUE_GREED:                            return L"Blue Greed";
-       case CRD_BLUE_INGEST:                           return L"Blue Ingest";
-       case CRD_BLUE_SD_DUALLINK:                      return L"Blue SD Duallink";
-       case CRD_BLUE_CATALYST:                         return L"Blue Catalyst";
-       case CRD_BLUE_SD_DUALLINK_PRO:          return L"Blue SD Duallink Pro";
-       case CRD_BLUE_SD_INGEST_PRO:            return L"Blue SD Ingest pro";
-       case CRD_BLUE_SD_DEEPBLUE_LITE_PRO:     return L"Blue SD Deepblue lite Pro";
-       case CRD_BLUE_SD_SINGLELINK_PRO:        return L"Blue SD Singlelink Pro";
-       case CRD_BLUE_SD_IRIDIUM_AV_PRO:        return L"Blue SD Iridium AV Pro";
-       case CRD_BLUE_SD_FIDELITY:                      return L"Blue SD Fidelity";
-       case CRD_BLUE_SD_FOCUS:                         return L"Blue SD Focus";
-       case CRD_BLUE_SD_PRIME:                         return L"Blue SD Prime";
-       case CRD_BLUE_EPOCH_2K_CORE:            return L"Blue Epoch 2K Core";
-       case CRD_BLUE_EPOCH_2K_ULTRA:           return L"Blue Epoch 2K Ultra";
-       case CRD_BLUE_EPOCH_HORIZON:            return L"Blue Epoch Horizon";
-       case CRD_BLUE_EPOCH_CORE:                       return L"Blue Epoch Core";
-       case CRD_BLUE_EPOCH_ULTRA:                      return L"Blue Epoch Ultra";
-       case CRD_BLUE_CREATE_HD:                        return L"Blue Create HD";
-       case CRD_BLUE_CREATE_2K:                        return L"Blue Create 2K";
-       case CRD_BLUE_CREATE_2K_ULTRA:          return L"Blue Create 2K Ultra";
-       default:                                                        return L"Unknown";
-       }
+       BLUE_UINT32 val = 0;
+       blue.QueryCardProperty32(EPOCH_GET_PRODUCT_ID, val);
+
+       if (val == ORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID)
+               return true;
+       else
+               return false;
 }
 
-EVideoMode get_video_mode(CBlueVelvet4& blue, const core::video_format_desc& format_desc)
+bool is_epoch_neutron_3o_card(BvcWrapper& blue)
 {
-       EVideoMode vid_fmt = VID_FMT_INVALID;
-       auto desiredVideoFormat = vid_fmt_from_video_format(format_desc.format);
-       int videoModeCount = blue.count_video_mode();
-       for(int videoModeIndex = 1; videoModeIndex <= videoModeCount; ++videoModeIndex) 
+       BLUE_UINT32 val = 0;
+       blue.QueryCardProperty32(EPOCH_GET_PRODUCT_ID, val);
+
+       if (val == ORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID)
+               return true;
+       else
+               return false;
+}
+
+
+std::wstring get_card_desc(BvcWrapper& blue, int iDeviceID)
+{
+       int iCardType = 0;
+       blue.QueryCardType(iCardType, iDeviceID);
+
+       switch(iCardType) 
        {
-               EVideoMode videoMode = blue.enum_video_mode(videoModeIndex);
-               if(videoMode == desiredVideoFormat) 
-                       vid_fmt = videoMode;                    
+               case CRD_BLUEDEEP_LT:                           return L"Deepblue LT";// D64 Lite
+               case CRD_BLUEDEEP_SD:                           return L"Iridium SD";// Iridium SD
+               case CRD_BLUEDEEP_AV:                           return L"Iridium AV";// Iridium AV
+               case CRD_BLUEDEEP_IO:                           return L"Deepblue IO";// D64 Full
+               case CRD_BLUEWILD_AV:                           return L"Wildblue AV";// D64 AV
+               case CRD_IRIDIUM_HD:                            return L"Iridium HD";// * Iridium HD
+               case CRD_BLUEWILD_RT:                           return L"Wildblue RT";// D64 RT
+               case CRD_BLUEWILD_HD:                           return L"Wildblue HD";// * BadAss G2
+               case CRD_REDDEVIL:                                      return L"Iridium Full";// Iridium Full
+               case CRD_BLUEDEEP_HD:   
+               case CRD_BLUEDEEP_HDS:                          return L"Reserved for \"BasAss G2";// * BadAss G2 variant, proposed, reserved
+               case CRD_BLUE_ENVY:                                     return L"Blue Envy"; // Mini Din 
+               case CRD_BLUE_PRIDE:                            return L"Blue Pride";//Mini Din Output 
+               case CRD_BLUE_GREED:                            return L"Blue Greed";
+               case CRD_BLUE_INGEST:                           return L"Blue Ingest";
+               case CRD_BLUE_SD_DUALLINK:                      return L"Blue SD Duallink";
+               case CRD_BLUE_CATALYST:                         return L"Blue Catalyst";
+               case CRD_BLUE_SD_DUALLINK_PRO:          return L"Blue SD Duallink Pro";
+               case CRD_BLUE_SD_INGEST_PRO:            return L"Blue SD Ingest pro";
+               case CRD_BLUE_SD_DEEPBLUE_LITE_PRO:     return L"Blue SD Deepblue lite Pro";
+               case CRD_BLUE_SD_SINGLELINK_PRO:        return L"Blue SD Singlelink Pro";
+               case CRD_BLUE_SD_IRIDIUM_AV_PRO:        return L"Blue SD Iridium AV Pro";
+               case CRD_BLUE_SD_FIDELITY:                      return L"Blue SD Fidelity";
+               case CRD_BLUE_SD_FOCUS:                         return L"Blue SD Focus";
+               case CRD_BLUE_SD_PRIME:                         return L"Blue SD Prime";
+               case CRD_BLUE_EPOCH_2K_CORE:            return L"Blue Epoch 2K Core";
+               case CRD_BLUE_EPOCH_2K_ULTRA:           return L"Blue Epoch 2K Ultra";
+               case CRD_BLUE_EPOCH_HORIZON:            return L"Blue Epoch Horizon";
+               case CRD_BLUE_EPOCH_CORE:                       return L"Blue Epoch Core";
+               case CRD_BLUE_EPOCH_ULTRA:                      return L"Blue Epoch Ultra";
+               case CRD_BLUE_CREATE_HD:                        return L"Blue Create HD";
+               case CRD_BLUE_CREATE_2K:                        return L"Blue Create 2K";
+               case CRD_BLUE_CREATE_2K_ULTRA:          return L"Blue Create 2K Ultra";
+               case CRD_BLUE_SUPER_NOVA:                       return L"Blue SuperNova";
+               case CRD_BLUE_SUPER_NOVA_S_PLUS:        return L"Blue SuperNova s+";
+               case CRD_BLUE_NEUTRON:                          return L"Blue Neutron 4k";
+               case CRD_BLUE_EPOCH_CG:                         return L"Blue Epopch CG";
+               default:                                                        return L"Unknown";
        }
-       if(vid_fmt == VID_FMT_INVALID)
+}
+
+EVideoMode get_video_mode(BvcWrapper& blue, const core::video_format_desc& format_desc)
+{
+       EVideoMode vid_fmt = VID_FMT_INVALID;
+       BLUE_UINT32 inValidFmt = 0;
+       BErr err = 0;
+       err = blue.QueryCardProperty32(INVALID_VIDEO_MODE_FLAG, inValidFmt);
+       vid_fmt = vid_fmt_from_video_format(format_desc.format);
+
+       if (vid_fmt == VID_FMT_INVALID)
                CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported: " + format_desc.name));
 
+
+       if ((unsigned int)vid_fmt >= inValidFmt)
+               CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported - Outside of valid range: " + format_desc.name));
+
        return vid_fmt;
 }
 
-spl::shared_ptr<CBlueVelvet4> create_blue()
+spl::shared_ptr<BvcWrapper> create_blue()
 {
-       if(!BlueVelvetFactory4 || !encode_hanc_frame)
+       auto pWrap = new BvcWrapper();
+       if (!pWrap->IsBvcValid())
                CASPAR_THROW_EXCEPTION(not_supported() << msg_info("Bluefish drivers not found."));
 
-       return spl::shared_ptr<CBlueVelvet4>(BlueVelvetFactory4(), BlueVelvetDestroy);
+       return spl::shared_ptr<BvcWrapper>(pWrap);
 }
 
-spl::shared_ptr<CBlueVelvet4> create_blue(int device_index)
+spl::shared_ptr<BvcWrapper> create_blue(int device_index)
 {
        auto blue = create_blue();
        
-       if(BLUE_FAIL(blue->device_attach(device_index, FALSE))) 
+       if(BLUE_FAIL(blue->Attach(device_index)))
                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to attach device."));
 
        return blue;
 }
 
+core::video_format video_format_from_vid_fmt(EVideoMode fmt)
+{
+       switch (fmt)
+       {
+       case VID_FMT_PAL: return core::video_format::pal;
+       case VID_FMT_NTSC: return core::video_format::ntsc;
+       case VID_FMT_720P_2398: return core::video_format::x720p2398;
+       case VID_FMT_720P_2400: return core::video_format::x720p2400;
+       case VID_FMT_720P_2500: return core::video_format::x720p2500;
+       case VID_FMT_720P_5000: return core::video_format::x720p5000;
+       case VID_FMT_720P_2997: return core::video_format::x720p2997;
+       case VID_FMT_720P_5994: return core::video_format::x720p5994;
+       case VID_FMT_720P_3000: return core::video_format::x720p3000;
+       case VID_FMT_720P_6000: return core::video_format::x720p6000;
+       case VID_FMT_1080P_2397: return core::video_format::x1080p2398;
+       case VID_FMT_1080P_2400: return core::video_format::x1080p2400;
+       case VID_FMT_1080I_5000: return core::video_format::x1080i5000;
+       case VID_FMT_1080I_5994: return core::video_format::x1080i5994;
+       case VID_FMT_1080I_6000: return core::video_format::x1080i6000;
+       case VID_FMT_1080P_2500: return core::video_format::x1080p2500;
+       case VID_FMT_1080P_2997: return core::video_format::x1080p2997;
+       case VID_FMT_1080P_3000: return core::video_format::x1080p3000;
+       case VID_FMT_1080P_5000: return core::video_format::x1080p5000;
+       case VID_FMT_1080P_5994: return core::video_format::x1080p5994;
+       case VID_FMT_1080P_6000: return core::video_format::x1080p6000;
+       default: return core::video_format::invalid;
+       }
+}
+
+core::video_format_desc get_format_desc(BvcWrapper& blue, EVideoMode vid_fmt, EMemoryFormat mem_fmt)
+{
+       core::video_format_desc fmt;
+       unsigned int width, height, duration = 0, time_scale = 0, rate = 0, bIs1001 = 0, bIsProgressive = 0, size = 0;
+       std::vector<int>        audio_cadence;
+       core::field_mode video_field_mode = core::field_mode::progressive;
+
+       blue.GetFrameInfoForVideoVode(vid_fmt, width, height, rate, bIs1001, bIsProgressive);
+       blue.GetBytesPerFrame(vid_fmt, mem_fmt, UPD_FMT_FRAME, size);
+
+       switch (vid_fmt)
+       {
+       case VID_FMT_NTSC:
+       case VID_FMT_1080I_5994:
+               duration = 30000;
+               time_scale = 1001;
+               audio_cadence = { 1601,1602,1601,1602,1602 };
+               video_field_mode = core::field_mode::upper;
+               break;
+       case VID_FMT_2048_1080P_2500:
+       case VID_FMT_2048_1080PSF_2500:
+       case VID_FMT_576I_5000:
+       case VID_FMT_1080P_2500:
+       case VID_FMT_1080I_5000:
+       case VID_FMT_1080PSF_2500:
+       case VID_FMT_720P_2500:
+               duration = 25000;
+               time_scale = 1000;
+               audio_cadence = { 1920,1920,1920,1920,1920 };
+               break;
+
+       case VID_FMT_720P_5994:
+       case VID_FMT_2048_1080P_5994:
+       case VID_FMT_1080P_5994:
+               duration = 60000;
+               time_scale = 1001;
+               audio_cadence = { 801,800,801,800,800 };
+               break;
+
+       case VID_FMT_1080P_6000:
+       case VID_FMT_2048_1080P_6000:
+       case VID_FMT_720P_6000:
+               duration = 60000;
+               time_scale = 1000;
+               audio_cadence = { 801,800,801,800,800 };
+               break;
+
+       case VID_FMT_1080PSF_2397:
+       case VID_FMT_1080P_2397:
+       case VID_FMT_720P_2398:
+       case VID_FMT_2048_1080PSF_2397:
+       case VID_FMT_2048_1080P_2397:
+               duration = 24000;
+               time_scale = 1000;
+               break;
+
+       case VID_FMT_1080PSF_2400:
+       case VID_FMT_1080P_2400:
+       case VID_FMT_720P_2400:
+       case VID_FMT_2048_1080PSF_2400:
+       case VID_FMT_2048_1080P_2400:
+               duration = 24000;
+               time_scale = 1000;
+               break;
+
+       case VID_FMT_1080I_6000:
+       case VID_FMT_1080PSF_3000:
+               duration = 30000;
+               time_scale = 1000;
+               break;
+
+       case VID_FMT_720P_2997:
+       case VID_FMT_1080P_2997:
+       case VID_FMT_2048_1080PSF_2997:
+       case VID_FMT_2048_1080P_2997:
+       case VID_FMT_1080PSF_2997:
+               duration = 30000;
+               time_scale = 1001;
+               break;
+
+       case VID_FMT_720P_3000:
+       case VID_FMT_1080P_3000:
+       case VID_FMT_2048_1080PSF_3000:
+       case VID_FMT_2048_1080P_3000:
+               duration = 30000;
+               time_scale = 1001;
+               break;
+
+       case VID_FMT_720P_5000:
+       case VID_FMT_1080P_5000:
+       case VID_FMT_2048_1080P_5000:
+               audio_cadence = { 960,960,960,960,960 };
+               duration = 50000;
+               time_scale = 1000;
+               break;
+               /*case VID_FMT_1080P_4800:
+               case VID_FMT_2048_1080P_4800:
+               fmt.duration = 48000;
+               fmt.time_scale = 1000;
+               break;*/
+       }
+       fmt = core::video_format_desc(video_format_from_vid_fmt(vid_fmt), width, height, width, height, video_field_mode, time_scale, duration, std::wstring(L""), audio_cadence);
+       fmt.size = size;
+       return fmt;
+}
+
 }}
\ No newline at end of file
index b20f97ba609c17e84427cfe100fd0e4eda017ac0..0f1fec754ac50280c0dfa629ae704d4bfe3d7c5e 100644 (file)
@@ -23,8 +23,7 @@
 
 #include <Windows.h>
 
-#include <BlueVelvet4.h>
-#include <BlueHancUtils.h>
+#include <bluefish/interop/BlueVelvetC.h>
 
 #include <common/memory.h>
 #include <common/except.h>
 
 namespace caspar { namespace bluefish {
 
-extern const char* (*BlueVelvetVersion)();
-extern BLUE_UINT32 (*encode_hanc_frame)(struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr,BLUE_UINT32 no_audio_ch,BLUE_UINT32 no_audio_samples,BLUE_UINT32 nTypeOfSample,BLUE_UINT32 emb_audio_flag);
-extern BLUE_UINT32 (*encode_hanc_frame_ex)(BLUE_UINT32 card_type, struct hanc_stream_info_struct * hanc_stream_ptr, void * audio_pcm_ptr, BLUE_UINT32 no_audio_ch,     BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag);
-
-void blue_initialize();
-
-spl::shared_ptr<CBlueVelvet4> create_blue();
-spl::shared_ptr<CBlueVelvet4> create_blue(int device_index);
-bool is_epoch_card(CBlueVelvet4& blue);
-std::wstring get_card_desc(CBlueVelvet4& blue);
-EVideoMode get_video_mode(CBlueVelvet4& blue, const core::video_format_desc& format_desc);
 
 template<typename T>
 int set_card_property(T& pSdk, ULONG prop, ULONG value)
 {
-       VARIANT variantValue;
-       variantValue.vt  = VT_UI4;
-       variantValue.ulVal = value;
-       return (pSdk->SetCardProperty(prop,variantValue));
+       return (pSdk->SetCardProperty32(prop, value));
 }
 
+template<typename T>
+int get_card_property(T& pSdk, ULONG prop, ULONG& value)
+{
+       unsigned int val = 0;
+       int retVal = pSdk->QueryCardProperty32(prop, val);
+       value = val;
+       return retVal;
+}
+
+class BvcWrapper
+{
+       // Define a different type for each of the function ptrs.
+       typedef const char* (__cdecl *pFunc_bfcGetVersion)();
+       typedef BLUEVELVETC_HANDLE(__cdecl *pFunc_bfcFactory)();
+       typedef void(__cdecl *pFunc_bfcDestroy)(BLUEVELVETC_HANDLE pHandle);
+       typedef int(__cdecl *pFunc_bfcEnumerate)(BLUEVELVETC_HANDLE pHandle, int& iDevices);
+       typedef int(__cdecl *pFunc_bfcQueryCardType)(BLUEVELVETC_HANDLE pHandle, int& iCardType, int iDeviceID);
+       typedef int(__cdecl *pFunc_bfcAttach)(BLUEVELVETC_HANDLE pHandle, int iDeviceId);
+       typedef int(__cdecl *pFunc_bfcDetach)(BLUEVELVETC_HANDLE pHandle);
+       typedef int(__cdecl *pFunc_bfcQueryCardProperty32)(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned int& nValue);
+       typedef int(__cdecl *pFunc_bfcQueryCardProperty64)(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned long long& ullValue);
+       typedef int(__cdecl *pFunc_bfcSetCardProperty32)(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned int nValue);
+       typedef int(__cdecl *pFunc_bfcSetCardProperty64)(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned long long ullValue);
+       typedef int(__cdecl *pFunc_bfcGetCardSerialNumber)(BLUEVELVETC_HANDLE pHandle, char* pSerialNumber, unsigned int nStringSize);
+       typedef int(__cdecl *pFunc_bfcGetCardFwVersion)(BLUEVELVETC_HANDLE pHandle, unsigned int& nValue);
+       typedef int(__cdecl *pFunc_bfcWaitVideoSyncAsync)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, blue_video_sync_struct* pSyncData);
+       typedef int(__cdecl *pFunc_bfcWaitVideoInputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount);
+       typedef int(__cdecl *pFunc_bfcWaitVideoOutputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount);
+       typedef int(__cdecl *pFunc_bfcGetVideoOutputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount);
+       typedef int(__cdecl *pFunc_bfcGetVideoInputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount);
+       typedef int(__cdecl *pFunc_bfcVideoCaptureStart)(BLUEVELVETC_HANDLE pHandle);
+       typedef int(__cdecl *pFunc_bfcVideoCaptureStop)(BLUEVELVETC_HANDLE pHandle);
+       typedef int(__cdecl *pFunc_bfcVideoPlaybackStart)(BLUEVELVETC_HANDLE pHandle, int iStep, int iLoop);
+       typedef int(__cdecl *pFunc_bfcVideoPlaybackStop)(BLUEVELVETC_HANDLE pHandle, int iWait, int iFlush);
+       typedef int(__cdecl *pFunc_bfcVideoPlaybackAllocate)(BLUEVELVETC_HANDLE pHandle, void** pAddress, unsigned long& ulBufferID, unsigned long& ulUnderrun);
+       typedef int(__cdecl *pFunc_bfcVideoPlaybackPresent)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulUniqueID, unsigned long ulBufferID, unsigned long ulCount, int iKeep, int iOdd);
+       typedef int(__cdecl *pFunc_bfcVideoPlaybackRelease)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID);
+       typedef int(__cdecl *pFunc_bfcGetCaptureVideoFrameInfoEx)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, struct blue_videoframe_info_ex& VideoFrameInfo, int iCompostLater, unsigned int* nCaptureFifoSize);
+       typedef int(__cdecl *pFunc_bfcRenderBufferCapture)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID);
+       typedef int(__cdecl *pFunc_bfcRenderBufferUpdate)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID);
+       typedef int(__cdecl *pFunc_bfcGetRenderBufferCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulCount);
+       typedef int(__cdecl *pFunc_bfcEncodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, struct hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags);
+       typedef int(__cdecl *pFunc_bfcDecodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo);
+#if defined(_WIN32)
+       typedef int(__cdecl *pFunc_bfcSystemBufferReadAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset);
+       typedef int(__cdecl *pFunc_bfcSystemBufferWriteAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset);
+#else
+       typedef int(__cdecl *pFunc_bfcSystemBufferRead)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset;
+       typedef int(__cdecl *pFunc_bfcSystemBufferWrite)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset;
+#endif
+       typedef int(__cdecl *pFunc_bfcGetBytesForGroupPixels)(EMemoryFormat nMemoryFormat, unsigned int nVideoWidth, unsigned int& nVideoPitchBytes);
+       typedef int(__cdecl *pFunc_bfcGetPixelsPerLine)(EVideoMode nVideoMode, unsigned int& nPixelsPerLine);
+       typedef int(__cdecl *pFunc_bfcGetLinesPerFrame)(EVideoMode nVideoMode, EUpdateMethod nUpdateMethod, unsigned int& nLinesPerFrame);
+       typedef int(__cdecl *pFunc_bfcGetBytesPerLine)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nBytesPerLine);
+       typedef int(__cdecl *pFunc_bfcGetBytesPerFrame)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame);
+       typedef int(__cdecl *pFunc_bfcGetGoldenValue)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nGoldenFrameSize);
+       typedef int(__cdecl *pFunc_bfcGetVBILines)(EVideoMode nVideoMode, EDMADataType nDataType, unsigned int& nVBILinesPerFrame);
+       typedef int(__cdecl *pFunc_bfcGetVANCGoldenValue)(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EDMADataType nDataFormat, unsigned int& nVANCGoldenValue);
+       typedef int(__cdecl *pFunc_bfcGetVANCLineBytes)(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nVANCLineBytes);
+       typedef int(__cdecl *pFunc_bfcGetVANCLineCount)(unsigned int nCardType, EVideoMode nVideoMode, EDMADataType nDataFormat, unsigned int& nVANCLineCount);
+       typedef int(__cdecl *pFunc_bfcGetWindowsDriverHandle)(BLUEVELVETC_HANDLE pHandle, HANDLE* pDriverHandle);
+       typedef int(__cdecl *pFunc_bfcSetDynamicMemoryFormatChange)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, unsigned int nUniqueId, EMemoryFormat nMemoryFormat);
+
+       //BlueVelvetC utils functions
+       typedef char*(__cdecl *pFunc_bfcUtilsGetStringForCardType)(const int iCardType);
+       typedef char*(__cdecl *pFunc_bfcUtilsGetStringForBlueProductId)(const unsigned int nProductId);
+       typedef char*(__cdecl *pFunc_bfcUtilsGetStringForVideoMode)(const unsigned int nVideoMode);
+       typedef char*(__cdecl *pFunc_bfcUtilsGetStringForMemoryFormat)(const unsigned int nMemoryFormat);
+       typedef int(__cdecl *pFunc_bfcUtilsGetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, unsigned int& nSrcNode, const unsigned int nDestNode, unsigned int& nLinkType);
+       typedef int(__cdecl *pFunc_bfcUtilsSetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nSrcNode, const unsigned int nDestNode, const unsigned int nLinkType);
+       typedef int(__cdecl *pFunc_bfcUtilsGetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int& nAudioSourceChannelId, unsigned int nAudioConnectorId);
+       typedef int(__cdecl *pFunc_bfcUtilsSetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int nAudioSourceChannelId, unsigned int nAudioConnectorId);
+       typedef bool(__cdecl *pFunc_bfcUtilsIsVideoModeProgressive)(const unsigned int nVideoMode);
+       typedef bool(__cdecl *pFunc_bfcUtilsIsVideoMode1001Framerate)(const unsigned int nVideoMode);
+       typedef int(__cdecl *pFunc_bfcUtilsGetFpsForVideoMode)(const unsigned int nVideoMode);
+       typedef int(__cdecl *pFunc_bfcUtilsGetVideoModeForFrameInfo)(const BLUE_UINT32 nWidth, const BLUE_UINT32 nHeight, const BLUE_UINT32 nRate, const BLUE_UINT32 bIs1001, const BLUE_UINT32 bIsProgressive, BLUE_UINT32& nVideoMode);
+       typedef int(__cdecl *pFunc_bfcUtilsGetFrameInfoForVideoMode)(const BLUE_UINT32 nVideoMode, BLUE_UINT32&  nWidth, BLUE_UINT32& nHeight, BLUE_UINT32& nRate, BLUE_UINT32& bIs1001, BLUE_UINT32& bIsProgressive);
+       typedef int(__cdecl *pFunc_bfcUtilsGetAudioSamplesPerFrame)(const BLUE_UINT32 nVideoMode, const BLUE_UINT32 nFrameNo);
+
+
+public:
+
+       BvcWrapper();                                           // bfcFactory
+       ~BvcWrapper();                                          // bfcDestory
+
+       bool            IsBvcValid();
+       const char*     GetVersion();
+
+       BLUE_UINT32 Enumerate(int& iDevices);
+       BLUE_UINT32 QueryCardType(int& iCardType, int iDeviceID);
+
+       BLUE_UINT32 Attach(int iDeviceId);
+       BLUE_UINT32 Detach();
+
+       BLUE_UINT32 QueryCardProperty32(const int iProperty, unsigned int& nValue);
+       BLUE_UINT32 SetCardProperty32(const int iProperty, const unsigned int nValue);
+       
+       BLUE_UINT32 SystemBufferWrite(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);
+       BLUE_UINT32 SystemBufferRead(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);
+
+       BLUE_UINT32 VideoPlaybackStop(int iWait, int iFlush);
+       BLUE_UINT32 WaitVideoOutputSync(unsigned long ulUpdateType, unsigned long& ulFieldCount);
+       BLUE_UINT32 WaitVideoInputSync(unsigned long ulUpdateType, unsigned long & ulFieldCount);
+
+       BLUE_UINT32 RenderBufferUpdate(unsigned long ulBufferID);
+       BLUE_UINT32 RenderBufferCapture(unsigned long ulBufferID);
+
+       BLUE_UINT32 EncodeHancFrameEx(unsigned int nCardType, struct hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags);
+       BLUE_UINT32 DecodeHancFrameEx(unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo);
+
+       BLUE_UINT32 GetFrameInfoForVideoVode(const unsigned int nVideoMode, unsigned int&  nWidth, unsigned int& nHeight, unsigned int& nRate, unsigned int& bIs1001, unsigned int& bIsProgressive);
+       BLUE_UINT32 GetBytesPerFrame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame);
+
+private:
+       bool                            InitFunctionsPointers();
+       BLUEVELVETC_HANDLE      bvc;
+#if defined(_WIN32)
+       HMODULE                         hModule;
+#else
+       void*                           hModule;
+#endif
+
+//BlueVelvetC function pointers members
+       pFunc_bfcGetVersion bfcGetVersion;
+       pFunc_bfcFactory bfcFactory;
+       pFunc_bfcDestroy bfcDestroy;
+       pFunc_bfcEnumerate bfcEnumerate;
+       pFunc_bfcQueryCardType bfcQueryCardType;
+       pFunc_bfcAttach bfcAttach;
+       pFunc_bfcDetach bfcDetach;
+       pFunc_bfcQueryCardProperty32 bfcQueryCardProperty32;
+       pFunc_bfcQueryCardProperty64 bfcQueryCardProperty64;
+       pFunc_bfcSetCardProperty32 bfcSetCardProperty32;
+       pFunc_bfcSetCardProperty64 bfcSetCardProperty64;
+       pFunc_bfcGetCardSerialNumber bfcGetCardSerialNumber;
+       pFunc_bfcGetCardFwVersion bfcGetCardFwVersion;
+       pFunc_bfcWaitVideoSyncAsync bfcWaitVideoSyncAsync;
+       pFunc_bfcWaitVideoInputSync bfcWaitVideoInputSync;
+       pFunc_bfcWaitVideoOutputSync bfcWaitVideoOutputSync;
+       pFunc_bfcGetVideoOutputCurrentFieldCount bfcGetVideoOutputCurrentFieldCount;
+       pFunc_bfcGetVideoInputCurrentFieldCount bfcGetVideoInputCurrentFieldCount;
+       pFunc_bfcVideoCaptureStart bfcVideoCaptureStart;
+       pFunc_bfcVideoCaptureStop bfcVideoCaptureStop;
+       pFunc_bfcVideoPlaybackStart bfcVideoPlaybackStart;
+       pFunc_bfcVideoPlaybackStop bfcVideoPlaybackStop;
+       pFunc_bfcVideoPlaybackAllocate bfcVideoPlaybackAllocate;
+       pFunc_bfcVideoPlaybackPresent bfcVideoPlaybackPresent;
+       pFunc_bfcVideoPlaybackRelease bfcVideoPlaybackRelease;
+       pFunc_bfcGetCaptureVideoFrameInfoEx bfcGetCaptureVideoFrameInfoEx;
+       pFunc_bfcRenderBufferCapture bfcRenderBufferCapture;
+       pFunc_bfcRenderBufferUpdate bfcRenderBufferUpdate;
+       pFunc_bfcGetRenderBufferCount bfcGetRenderBufferCount;
+       pFunc_bfcEncodeHancFrameEx bfcEncodeHancFrameEx;
+       pFunc_bfcDecodeHancFrameEx bfcDecodeHancFrameEx;
+#if defined(_WIN32)
+       pFunc_bfcSystemBufferReadAsync bfcSystemBufferReadAsync;
+       pFunc_bfcSystemBufferWriteAsync bfcSystemBufferWriteAsync;
+#else
+       pFunc_bfcSystemBufferRead bfcSystemBufferRead;
+    pFunc_bfcSystemBufferWrite bfcSystemBufferWrite;
+#endif
+       pFunc_bfcGetBytesForGroupPixels bfcGetBytesForGroupPixels;
+       pFunc_bfcGetPixelsPerLine bfcGetPixelsPerLine;
+       pFunc_bfcGetLinesPerFrame bfcGetLinesPerFrame;
+       pFunc_bfcGetBytesPerLine bfcGetBytesPerLine;
+       pFunc_bfcGetBytesPerFrame bfcGetBytesPerFrame;
+       pFunc_bfcGetGoldenValue bfcGetGoldenValue;
+       pFunc_bfcGetVBILines bfcGetVBILines;
+       pFunc_bfcGetVANCGoldenValue bfcGetVANCGoldenValue;
+       pFunc_bfcGetVANCLineBytes bfcGetVANCLineBytes;
+       pFunc_bfcGetVANCLineCount bfcGetVANCLineCount;
+       pFunc_bfcGetWindowsDriverHandle bfcGetWindowsDriverHandle;
+       pFunc_bfcUtilsGetStringForCardType bfcUtilsGetStringForCardType;
+       pFunc_bfcUtilsGetStringForBlueProductId bfcUtilsGetStringForBlueProductId;
+       pFunc_bfcUtilsGetStringForVideoMode bfcUtilsGetStringForVideoMode;
+       pFunc_bfcUtilsGetStringForMemoryFormat bfcUtilsGetStringForMemoryFormat;
+       pFunc_bfcUtilsGetMR2Routing bfcUtilsGetMR2Routing;
+       pFunc_bfcUtilsSetMR2Routing bfcUtilsSetMR2Routing;
+       pFunc_bfcUtilsGetAudioOutputRouting bfcUtilsGetAudioOutputRouting;
+       pFunc_bfcUtilsSetAudioOutputRouting bfcUtilsSetAudioOutputRouting;
+       pFunc_bfcUtilsIsVideoModeProgressive bfcUtilsIsVideoModeProgressive;
+       pFunc_bfcUtilsIsVideoMode1001Framerate bfcUtilsIsVideoMode1001Framerate;
+       pFunc_bfcUtilsGetFpsForVideoMode bfcUtilsGetFpsForVideoMode;
+       pFunc_bfcUtilsGetVideoModeForFrameInfo bfcUtilsGetVideoModeForFrameInfo;
+       pFunc_bfcUtilsGetFrameInfoForVideoMode bfcUtilsGetFrameInfoForVideoMode;
+       pFunc_bfcUtilsGetAudioSamplesPerFrame bfcUtilsGetAudioSamplesPerFrame;
+
+};
+
+spl::shared_ptr<BvcWrapper> create_blue();
+spl::shared_ptr<BvcWrapper> create_blue(int device_index);
+
+//spl::shared_ptr<BvcWrapper> create_blue();
+
+bool is_epoch_card(BvcWrapper& blue);
+bool is_epoch_neutron_1i2o_card(BvcWrapper& blue);
+bool is_epoch_neutron_3o_card(BvcWrapper& blue);
+std::wstring get_card_desc(BvcWrapper& blue, int device_index);
+EVideoMode get_video_mode(BvcWrapper& blue, const core::video_format_desc& format_desc);
+core::video_format_desc get_format_desc(BvcWrapper& blue, EVideoMode vid_fmt, EMemoryFormat mem_fmt);
+
+
 }}
\ No newline at end of file
index 994cb8aeeb1aa8adf72292a832add296801b5ab6..79894cec2facaaec42334bcd36afe8f282c88b46 100644 (file)
@@ -23,8 +23,6 @@
 
 #include <Windows.h>
 
-#include <BlueVelvet4.h>
-
 #include <common/os/page_locked_allocator.h>
 
 #include <vector>