-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG.\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
- \r
-#include "..\..\StdAfx.h"\r
-\r
-#ifndef DISABLE_BLUEFISH\r
-\r
-#include <BlueVelvet4.h>\r
-#include "BlueFishVideoConsumer.h"\r
-#include "BluefishPlaybackStrategy.h"\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-\r
-#if defined(_MSC_VER)\r
-#pragma warning (push, 1) // TODO: Legacy code, just disable warnings\r
-#endif\r
-\r
-namespace caspar {\r
-namespace bluefish {\r
-\r
-///////////////////////////////////////////\r
-// BlueFishVideoConsumer::EnumerateDevices\r
-// RETURNS: Number of identified bluefish-cards\r
-int BlueFishVideoConsumer::EnumerateDevices()\r
-{\r
- CASPAR_LOG(info) << "Bleufhsi SDK version: " << BlueVelvetVersion;\r
- BlueVelvetPtr pSDK(BlueVelvetFactory4());\r
-\r
- if(pSDK != 0) {\r
- int deviceCount = 0;\r
- pSDK->device_enumerate(deviceCount);\r
- return deviceCount;\r
- }\r
- else\r
- return 0;\r
-}\r
-\r
-\r
-///////////////////////////////////////////\r
-// BlueFishVideoConsumer::Create\r
-// PARAMS: deviceIndex(index of the card that is to be wrapped in a consumer)\r
-// RETURNS: a new BlueFishVideoConsumer-object for the specified card\r
-// COMMENT: Creates and initializes a consumer that outputs video to a bluefish-card\r
-frame_consumer_ptr BlueFishVideoConsumer::Create(const frame_format_desc& format_desc, unsigned int deviceIndex)\r
-{\r
- BlueFishFrameConsumerPtr card(new BlueFishVideoConsumer(format_desc));\r
- if(card != 0 && card->SetupDevice(deviceIndex) == false)\r
- card.reset();\r
-\r
- return card;\r
-}\r
-\r
-////////////////////////////////////////\r
-// BlueFishVideoConsumer constructor\r
-BlueFishVideoConsumer::BlueFishVideoConsumer(const frame_format_desc& format_desc) : format_desc_(format_desc), pSDK_(BlueVelvetFactory4()), currentFormat_(frame_format::pal), _deviceIndex(0), hasEmbeddedAudio_(false)\r
-{\r
- frameBuffer_.set_capacity(1);\r
- thread_ = boost::thread([=]{Run();});\r
-}\r
-\r
-////////////////////////////////////////\r
-// BlueFishVideoConsumer destructor\r
-BlueFishVideoConsumer::~BlueFishVideoConsumer()\r
-{\r
- frameBuffer_.push(nullptr),\r
- thread_.join();\r
- ReleaseDevice();\r
-}\r
-\r
-/*******************/\r
-/** METHODS **/\r
-/*******************/\r
-\r
-unsigned long BlueFishVideoConsumer::VidFmtFromFrameFormat(frame_format fmt) \r
-{\r
- switch(fmt)\r
- {\r
- case frame_format::pal: return VID_FMT_PAL;\r
- case frame_format::ntsc: return VID_FMT_NTSC;\r
- case frame_format::x576p2500: return ULONG_MAX; //not supported\r
- case frame_format::x720p5000: return VID_FMT_720P_5000;\r
- case frame_format::x720p5994: return VID_FMT_720P_5994;\r
- case frame_format::x720p6000: return VID_FMT_720P_6000;\r
- case frame_format::x1080p2397: return VID_FMT_1080P_2397;\r
- case frame_format::x1080p2400: return VID_FMT_1080P_2400;\r
- case frame_format::x1080i5000: return VID_FMT_1080I_5000;\r
- case frame_format::x1080i5994: return VID_FMT_1080I_5994;\r
- case frame_format::x1080i6000: return VID_FMT_1080I_6000;\r
- case frame_format::x1080p2500: return VID_FMT_1080P_2500;\r
- case frame_format::x1080p2997: return VID_FMT_1080P_2997;\r
- case frame_format::x1080p3000: return VID_FMT_1080P_3000;\r
- default: return ULONG_MAX;\r
- }\r
-}\r
-\r
-TCHAR* GetBluefishCardDesc(int cardType) \r
-{\r
- switch(cardType) \r
- {\r
- case CRD_BLUEDEEP_LT: return TEXT("Deepblue LT"); // D64 Lite\r
- case CRD_BLUEDEEP_SD: return TEXT("Iridium SD"); // Iridium SD\r
- case CRD_BLUEDEEP_AV: return TEXT("Iridium AV"); // Iridium AV\r
- case CRD_BLUEDEEP_IO: return TEXT("Deepblue IO"); // D64 Full\r
- case CRD_BLUEWILD_AV: return TEXT("Wildblue AV"); // D64 AV\r
- case CRD_IRIDIUM_HD: return TEXT("Iridium HD"); // * Iridium HD\r
- case CRD_BLUEWILD_RT: return TEXT("Wildblue RT"); // D64 RT\r
- case CRD_BLUEWILD_HD: return TEXT("Wildblue HD"); // * BadAss G2\r
- case CRD_REDDEVIL: return TEXT("Iridium Full"); // Iridium Full\r
- case CRD_BLUEDEEP_HD: // * BadAss G2 variant, proposed, reserved\r
- case CRD_BLUEDEEP_HDS: return TEXT("Reserved for \"BasAss G2"); // * BadAss G2 variant, proposed, reserved\r
- case CRD_BLUE_ENVY: return TEXT("Blue envy"); // Mini Din \r
- case CRD_BLUE_PRIDE: return TEXT("Blue pride"); //Mini Din Output \r
- case CRD_BLUE_GREED: return TEXT("Blue greed");\r
- case CRD_BLUE_INGEST: return TEXT("Blue ingest");\r
- case CRD_BLUE_SD_DUALLINK: return TEXT("Blue SD duallink");\r
- case CRD_BLUE_CATALYST: return TEXT("Blue catalyst");\r
- case CRD_BLUE_SD_DUALLINK_PRO: return TEXT("Blue SD duallink pro");\r
- case CRD_BLUE_SD_INGEST_PRO: return TEXT("Blue SD ingest pro");\r
- case CRD_BLUE_SD_DEEPBLUE_LITE_PRO: return TEXT("Blue SD deepblue lite pro");\r
- case CRD_BLUE_SD_SINGLELINK_PRO: return TEXT("Blue SD singlelink pro");\r
- case CRD_BLUE_SD_IRIDIUM_AV_PRO: return TEXT("Blue SD iridium AV pro");\r
- case CRD_BLUE_SD_FIDELITY: return TEXT("Blue SD fidelity");\r
- case CRD_BLUE_SD_FOCUS: return TEXT("Blue SD focus");\r
- case CRD_BLUE_SD_PRIME: return TEXT("Blue SD prime");\r
- case CRD_BLUE_EPOCH_2K_CORE: return TEXT("Blue epoch 2k core");\r
- case CRD_BLUE_EPOCH_2K_ULTRA: return TEXT("Blue epoch 2k ultra");\r
- case CRD_BLUE_EPOCH_HORIZON: return TEXT("Blue epoch horizon");\r
- case CRD_BLUE_EPOCH_CORE: return TEXT("Blue epoch core");\r
- case CRD_BLUE_EPOCH_ULTRA: return TEXT("Blue epoch ultra");\r
- case CRD_BLUE_CREATE_HD: return TEXT("Blue create HD");\r
- case CRD_BLUE_CREATE_2K: return TEXT("Blue create 2k");\r
- case CRD_BLUE_CREATE_2K_ULTRA: return TEXT("Blue create 2k ultra");\r
- default: return TEXT("Unknown");\r
- }\r
-}\r
-\r
-bool BlueFishVideoConsumer::SetupDevice(unsigned int deviceIndex)\r
-{\r
- return this->DoSetupDevice(deviceIndex);\r
-}\r
-\r
-/*\r
-// Original initialization code\r
-bool BlueFishVideoConsumer::DoSetupDevice(unsigned int deviceIndex, std::wstring strDesiredFrameFormat)\r
-{\r
- _deviceIndex = deviceIndex;\r
-\r
- unsigned long memFmt = MEM_FMT_ARGB_PC, updFmt = UPD_FMT_FRAME, vidFmt = VID_FMT_PAL, resFmt = RES_FMT_NORMAL;\r
- unsigned long desiredVideoFormat = VID_FMT_PAL;\r
- int iDummy;\r
-\r
- int bufferIndex=0; //Bufferindex used when initializing the buffers\r
-\r
- if(strDesiredFrameFormat.size() == 0)\r
- strDesiredFrameFormat = TEXT("PAL");\r
-\r
- frame_format casparVideoFormat = caspar::get_video_format(strDesiredFrameFormat);\r
- desiredVideoFormat = BlueFishVideoConsumer::VidFmtFromFrameFormat(casparVideoFormat);\r
- currentFormat_ = casparVideoFormat != FFormatInvalid ? casparVideoFormat : FFormatPAL;\r
- if(desiredVideoFormat == ULONG_MAX) {\r
- LOG << TEXT("BLUECARD ERROR: Unsupported videomode: ") << strDesiredFrameFormat << TEXT(". (device") << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- if(BLUE_FAIL(pSDK_->device_attach(_deviceIndex, FALSE))) {\r
- LOG << TEXT("BLUECARD ERROR: Failed to attach device") << _deviceIndex;\r
- return false;\r
- }\r
-\r
- if(desiredVideoFormat != VID_FMT_PAL) {\r
- int videoModeCount = pSDK_->count_video_mode();\r
- for(int videoModeIndex=1; videoModeIndex <= videoModeCount; ++videoModeIndex) {\r
- EVideoMode videoMode = pSDK_->enum_video_mode(videoModeIndex);\r
- if(videoMode == desiredVideoFormat) {\r
- vidFmt = videoMode;\r
- }\r
- }\r
- }\r
-\r
- if(vidFmt == VID_FMT_PAL) {\r
- strDesiredFrameFormat = TEXT("PAL");\r
- currentFormat_ = FFormatPAL;\r
- }\r
-\r
- if(BLUE_FAIL(pSDK_->set_video_framestore_style(vidFmt, memFmt, updFmt, resFmt))) {\r
- LOG << TEXT("BLUECARD ERROR: Failed to set videomode to ") << strDesiredFrameFormat << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- LOG << TEXT("BLUECARD INFO: Successfully configured bluecard for ") << strDesiredFrameFormat << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
-\r
- if (pSDK_->has_output_key()) {\r
- iDummy = TRUE;\r
- int v4444 = FALSE, invert = FALSE, white = FALSE;\r
- pSDK_->set_output_key(iDummy, v4444, invert, white);\r
- }\r
-\r
- if(pSDK_->GetHDCardType(_deviceIndex) != CRD_HD_INVALID) {\r
- pSDK_->Set_DownConverterSignalType((vidFmt == VID_FMT_PAL) ? SD_SDI : HD_SDI);\r
- }\r
-\r
-\r
- iDummy = FALSE;\r
- pSDK_->set_vertical_flip(iDummy);\r
-\r
- // Get framestore parameters\r
- if(BLUE_OK(pSDK_->render_buffer_sizeof(m_bufferCount, m_length, m_actual, m_golden))) {\r
- LOG << TEXT("BLUECARD INFO: Buffers: ") << m_bufferCount << TEXT(", \"Length\": ") << m_length << TEXT(", Buffer size: ") << m_actual << TEXT(" (device ") << _deviceIndex << TEXT(")") << common::LogStream::Flush;\r
- }\r
- else {\r
- LOG << TEXT("BLUECARD ERROR: Failed to get framestore parameters (device ") << _deviceIndex << TEXT(")");\r
- }\r
-\r
- pFrameManager_ = BluefishFrameManagerPtr(new BluefishFrameManager(pSDK_, currentFormat_, m_golden));\r
-\r
- iDummy = TRUE;\r
- pSDK_->set_output_video(iDummy);\r
-\r
- // Now specify video output buffer\r
- pSDK_->render_buffer_update(0);\r
-\r
- pPlaybackControl_.reset(new FramePlaybackControl(FramePlaybackStrategyPtr(new BluefishPlaybackStrategy(this))));\r
- pPlaybackControl_->Start();\r
-\r
- LOG << TEXT("BLUECARD INFO: Successfully initialized device ") << _deviceIndex;\r
- return true;\r
-}\r
-*/\r
-\r
-//New, improved(?) initialization code. \r
-//Based on code sent from the bluefish-sdk support 2009-08-25. Email "RE: [sdk] Ang. RE: Issue with SD Lite Pro PCI-E"\r
-bool BlueFishVideoConsumer::DoSetupDevice(unsigned int deviceIndex)\r
-{\r
- _deviceIndex = deviceIndex;\r
-\r
- unsigned long memFmt = MEM_FMT_ARGB_PC, updFmt = UPD_FMT_FRAME, vidFmt = VID_FMT_PAL, resFmt = RES_FMT_NORMAL, engineMode = VIDEO_ENGINE_FRAMESTORE;\r
- unsigned long desiredVideoFormat = VID_FMT_PAL;\r
- int iDummy;\r
-\r
- int bufferIndex=0; //Bufferindex used when initializing the buffers\r
-\r
- if(BLUE_FAIL(pSDK_->device_attach(_deviceIndex, FALSE))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to attach device. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- int videoCardType = pSDK_->has_video_cardtype();\r
- CASPAR_LOG(info) << "BLUECARD INFO: Card type: " << GetBluefishCardDesc(videoCardType) << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
-\r
- desiredVideoFormat = BlueFishVideoConsumer::VidFmtFromFrameFormat(format_desc_.format);\r
- currentFormat_ = format_desc_.format != frame_format::invalid ? format_desc_.format : frame_format::pal;\r
- if(desiredVideoFormat == ULONG_MAX) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Unsupported videomode: " << format_desc_.name << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- if(desiredVideoFormat != VID_FMT_PAL) {\r
- int videoModeCount = pSDK_->count_video_mode();\r
- for(int videoModeIndex=1; videoModeIndex <= videoModeCount; ++videoModeIndex) {\r
- EVideoMode videoMode = pSDK_->enum_video_mode(videoModeIndex);\r
- if(videoMode == desiredVideoFormat) {\r
- vidFmt = videoMode;\r
- }\r
- }\r
- }\r
-\r
- if(vidFmt != desiredVideoFormat) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set desired videomode: " << format_desc_.name << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
- }\r
-\r
- if(vidFmt == VID_FMT_PAL) {\r
- currentFormat_ = frame_format::pal;\r
- format_desc_ = frame_format_desc::format_descs[frame_format::pal];\r
- }\r
-\r
- DisableVideoOutput();\r
-\r
- VARIANT value;\r
- value.vt = VT_UI4;\r
-\r
- //Enable dual link output\r
- value.ulVal = 1;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_DUAL_LINK_OUTPUT, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to enable dual link. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- value.ulVal = Signal_FormatType_4224;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set dual link format type to 4:2:2:4. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- //Setting output Video mode\r
- value.ulVal = vidFmt;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_MODE, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set videomode. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- //Select Update Mode for output\r
- value.ulVal = updFmt;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_UPDATE_TYPE, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set update type. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
- \r
- //Select output memory format\r
- value.ulVal = memFmt;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_MEMORY_FORMAT, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set memory format. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- //SELECT IMAGE ORIENTATION\r
- value.ulVal = ImageOrientation_Normal;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_IMAGE_ORIENTATION, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set image orientation to normal. (device " << _deviceIndex << TEXT(")");\r
- }\r
-\r
- value.ulVal = CGR_RANGE;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_RGB_DATA_RANGE, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set RGB data range to CGR. (device " << _deviceIndex << TEXT(")");\r
- }\r
-\r
- value.ulVal = MATRIX_709_CGR;\r
- if(vidFmt == VID_FMT_PAL) {\r
- value.ulVal = MATRIX_601_CGR;\r
- }\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_PREDEFINED_COLOR_MATRIX, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set colormatrix to " << (vidFmt == VID_FMT_PAL ? TEXT("601 CGR") : TEXT("709 CGR")) << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
- }\r
- \r
-\r
- //Disable embedded audio\r
- value.ulVal = 1;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(EMBEDDED_AUDIO_OUTPUT, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to enable embedded audio. (device " << _deviceIndex << TEXT(")");\r
- }\r
- else {\r
- CASPAR_LOG(info) << "BLUECARD INFO: Enabled embedded audio. (device " << _deviceIndex << TEXT(")");\r
- hasEmbeddedAudio_ = true;\r
- }\r
-\r
- CASPAR_LOG(info) << "BLUECARD INFO: Successfully configured bluecard for " << format_desc_.name << TEXT(". (device ") << _deviceIndex << TEXT(")");\r
-\r
- if (pSDK_->has_output_key()) {\r
- iDummy = TRUE;\r
- int v4444 = FALSE, invert = FALSE, white = FALSE;\r
- pSDK_->set_output_key(iDummy, v4444, invert, white);\r
- }\r
-\r
- if(pSDK_->GetHDCardType(_deviceIndex) != CRD_HD_INVALID) {\r
- pSDK_->Set_DownConverterSignalType((vidFmt == VID_FMT_PAL) ? SD_SDI : HD_SDI);\r
- }\r
-\r
- ULONG videoGolden = BlueVelvetGolden(vidFmt, memFmt, updFmt);\r
-\r
- pFrameManager_ = BluefishFrameManagerPtr(new BluefishFrameManager(pSDK_, currentFormat_, videoGolden));\r
-\r
- pPlayback_ = std::make_shared<BluefishPlaybackStrategy>(this);\r
-\r
- if(BLUE_FAIL(pSDK_->set_video_engine(engineMode))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to set vido engine. (device " << _deviceIndex << TEXT(")");\r
- return false;\r
- }\r
-\r
- EnableVideoOutput();\r
-\r
- CASPAR_LOG(info) << "BLUECARD INFO: Successfully initialized device " << _deviceIndex;\r
- return true;\r
-}\r
-\r
-bool BlueFishVideoConsumer::ReleaseDevice()\r
-{\r
- pPlayback_.reset();\r
-\r
- pFrameManager_.reset();\r
- DisableVideoOutput();\r
-\r
- if(pSDK_) {\r
- pSDK_->device_detach();\r
- }\r
-\r
- CASPAR_LOG(info) << "BLUECARD INFO: Successfully released device " << _deviceIndex;\r
- return true;\r
-}\r
-\r
-void BlueFishVideoConsumer::EnableVideoOutput()\r
-{\r
- //Need sync. protection?\r
- if(pSDK_)\r
- {\r
- VARIANT value;\r
- value.vt = VT_UI4;\r
-\r
- //Deactivate channel\r
- value.ulVal = 0;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_BLACKGENERATOR, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to disable video output. (device " << _deviceIndex << TEXT(")");\r
- }\r
- }\r
-}\r
-\r
-void BlueFishVideoConsumer::DisableVideoOutput()\r
-{\r
- //Need sync. protection?\r
- if(pSDK_)\r
- {\r
- VARIANT value;\r
- value.vt = VT_UI4;\r
-\r
- //Deactivate channel\r
- value.ulVal = 1;\r
- if(!BLUE_PASS(pSDK_->SetCardProperty(VIDEO_BLACKGENERATOR, value))) {\r
- CASPAR_LOG(error) << "BLUECARD ERROR: Failed to disable video output. (device " << _deviceIndex << TEXT(")");\r
- }\r
- }\r
-}\r
-\r
-void BlueFishVideoConsumer::display(const gpu_frame_ptr& frame)\r
-{\r
- if(frame == nullptr)\r
- return;\r
-\r
- if(pException_ != nullptr)\r
- std::rethrow_exception(pException_);\r
-\r
- frameBuffer_.push(frame);\r
-}\r
-\r
-void BlueFishVideoConsumer::Run()\r
-{\r
- while(true)\r
- {\r
- try\r
- {\r
- gpu_frame_ptr frame;\r
- frameBuffer_.pop(frame);\r
- if(frame == nullptr)\r
- return;\r
-\r
- pPlayback_->display(frame);\r
- }\r
- catch(...)\r
- {\r
- pException_ = std::current_exception();\r
- }\r
- } \r
-}\r
-\r
-}}\r
-\r
-#endif
\ No newline at end of file