]> git.sesse.net Git - casparcg/blob - modules/bluefish/util/blue_velvet.cpp
Disable audio output when closing a bf device after playback.
[casparcg] / modules / bluefish / util / blue_velvet.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Robert Nagy, ronag89@gmail.com
20 */
21
22 #include "../StdAfx.h"
23 #include "blue_velvet.h"
24 #include <common/utf.h> 
25 #include <core/video_format.h>
26 #include <BlueVelvetCUtils.h>
27
28 #if defined(__APPLE__)
29 #include <dlfcn.h>
30 #endif
31
32 #if defined(_WIN32)
33         #define GET_PROCADDR_FOR_FUNC(name, module) { name = (pFunc_##name)GetProcAddress(reinterpret_cast<HMODULE>(module), #name); if(!name) { return false; } }
34 //      #define GET_PROCADDR_FOR_FUNC(name, module) { name = (pFunc_##name)GetProcAddress(module, #name); if(!name) { return false; } }
35 #elif defined(__APPLE__)
36         #define GET_PROCADDR_FOR_FUNC(name, module) { name = (pFunc_##name)dlsym(module, #name); if(!name) { return false; } }
37 #endif
38
39 namespace caspar { namespace bluefish {
40
41         bvc_wrapper::bvc_wrapper()
42         {
43                 bvc_ = nullptr;
44                 h_module_ = nullptr;
45                 init_function_pointers();
46                 bvc_ = std::shared_ptr<void>(bfcFactory(), bfcDestroy);
47                 
48                 if (!bvc_)
49                         CASPAR_THROW_EXCEPTION(not_supported() << msg_info("Bluefish drivers not found."));
50         }
51
52         bool bvc_wrapper::init_function_pointers()
53         {
54                 bool res = false;
55                 bfcGetVersion = nullptr;
56                 bfcFactory = nullptr;
57                 bfcDestroy = nullptr;
58                 bfcEnumerate = nullptr;
59                 bfcQueryCardType = nullptr;
60                 bfcAttach = nullptr;
61                 bfcDetach = nullptr;
62                 bfcQueryCardProperty32 = nullptr;
63                 bfcQueryCardProperty64 = nullptr;
64                 bfcSetCardProperty32 = nullptr;
65                 bfcSetCardProperty64 = nullptr;
66                 bfcGetCardSerialNumber = nullptr;
67                 bfcGetCardFwVersion = nullptr;
68                 bfcWaitVideoSyncAsync = nullptr;
69                 bfcWaitVideoInputSync = nullptr;
70                 bfcWaitVideoOutputSync = nullptr;
71                 bfcGetVideoOutputCurrentFieldCount = nullptr;
72                 bfcGetVideoInputCurrentFieldCount = nullptr;
73                 bfcVideoCaptureStart = nullptr;
74                 bfcVideoCaptureStop = nullptr;
75                 bfcVideoPlaybackStart = nullptr;
76                 bfcVideoPlaybackStop = nullptr;
77                 bfcVideoPlaybackAllocate = nullptr;
78                 bfcVideoPlaybackPresent = nullptr;
79                 bfcVideoPlaybackRelease = nullptr;
80                 bfcGetCaptureVideoFrameInfoEx = nullptr;
81                 bfcRenderBufferCapture = nullptr;
82                 bfcRenderBufferUpdate = nullptr;
83                 bfcGetRenderBufferCount = nullptr;
84                 bfcEncodeHancFrameEx = nullptr;
85                 bfcDecodeHancFrameEx = nullptr;
86 #if defined(_WIN32)
87                 bfcSystemBufferReadAsync = nullptr;
88                 bfcSystemBufferWriteAsync = nullptr;
89 #else
90                 bfcSystemBufferRead = nullptr;
91                 bfcSystemBufferWrite = nullptr;
92 #endif
93                 bfcGetBytesForGroupPixels = nullptr;
94                 bfcGetPixelsPerLine = nullptr;
95                 bfcGetLinesPerFrame = nullptr;
96                 bfcGetBytesPerLine = nullptr;
97                 bfcGetBytesPerFrame = nullptr;
98                 bfcGetGoldenValue = nullptr;
99                 bfcGetVBILines = nullptr;
100                 bfcGetVANCGoldenValue = nullptr;
101                 bfcGetVANCLineBytes = nullptr;
102                 bfcGetVANCLineCount = nullptr;
103                 bfcGetWindowsDriverHandle = nullptr;
104                 bfcUtilsGetStringForCardType = nullptr;
105                 bfcUtilsGetStringForBlueProductId = nullptr;
106                 bfcUtilsGetStringForVideoMode = nullptr;
107                 bfcUtilsGetStringForMemoryFormat = nullptr;
108                 bfcUtilsGetMR2Routing = nullptr;
109                 bfcUtilsSetMR2Routing = nullptr;
110                 bfcUtilsGetAudioOutputRouting = nullptr;
111                 bfcUtilsSetAudioOutputRouting = nullptr;
112                 bfcUtilsIsVideoModeProgressive = nullptr;
113                 bfcUtilsIsVideoMode1001Framerate = nullptr;
114                 bfcUtilsGetFpsForVideoMode = nullptr;
115                 bfcUtilsGetVideoModeForFrameInfo = nullptr;
116                 bfcUtilsGetFrameInfoForVideoMode = nullptr;
117                 bfcUtilsGetAudioSamplesPerFrame = nullptr;
118
119 #if defined(_WIN32)
120 #ifdef _DEBUG
121                 h_module_ = std::shared_ptr<void>(LoadLibraryExA("BlueVelvetC64_d.dll", NULL, 0), FreeLibrary);
122 #else
123                 h_module_ = std::shared_ptr<void>(LoadLibraryExA("BlueVelvetC64.dll", NULL, 0), FreeLibrary);
124 #endif
125                 
126 #elif defined(__APPLE__)
127                 // Look for the framework and load it accordingly.
128                 char* libraryPath("/Library/Frameworks/BlueVelvetC.framework");         // full path may not be required, OSX might check in /l/f by default - MUST TEST!
129                 h_module_ = std::shared_ptr<void>(dlopen(libraryPath, RTLD_NOW), dlclose);
130 #endif
131                 
132                 if (h_module_)
133                 {
134                         GET_PROCADDR_FOR_FUNC(bfcGetVersion, h_module_.get());
135                         GET_PROCADDR_FOR_FUNC(bfcFactory, h_module_.get());
136                         GET_PROCADDR_FOR_FUNC(bfcDestroy, h_module_.get());
137                         GET_PROCADDR_FOR_FUNC(bfcEnumerate, h_module_.get());
138                         GET_PROCADDR_FOR_FUNC(bfcQueryCardType, h_module_.get());
139                         GET_PROCADDR_FOR_FUNC(bfcAttach, h_module_.get());
140                         GET_PROCADDR_FOR_FUNC(bfcDetach, h_module_.get());
141                         GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty32, h_module_.get());
142                         GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty64, h_module_.get());
143                         GET_PROCADDR_FOR_FUNC(bfcSetCardProperty32, h_module_.get());
144                         GET_PROCADDR_FOR_FUNC(bfcSetCardProperty64, h_module_.get());
145                         GET_PROCADDR_FOR_FUNC(bfcGetCardSerialNumber, h_module_.get());
146                         GET_PROCADDR_FOR_FUNC(bfcGetCardFwVersion, h_module_.get());
147                         GET_PROCADDR_FOR_FUNC(bfcWaitVideoSyncAsync, h_module_.get());
148                         GET_PROCADDR_FOR_FUNC(bfcWaitVideoInputSync, h_module_.get());
149                         GET_PROCADDR_FOR_FUNC(bfcWaitVideoOutputSync, h_module_.get());
150                         GET_PROCADDR_FOR_FUNC(bfcGetVideoOutputCurrentFieldCount, h_module_.get());
151                         GET_PROCADDR_FOR_FUNC(bfcGetVideoInputCurrentFieldCount, h_module_.get());
152                         GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStart, h_module_.get());
153                         GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStop, h_module_.get());
154                         GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStart, h_module_.get());
155                         GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStop, h_module_.get());
156                         GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackAllocate, h_module_.get());
157                         GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackPresent, h_module_.get());
158                         GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackRelease, h_module_.get());
159                         GET_PROCADDR_FOR_FUNC(bfcGetCaptureVideoFrameInfoEx, h_module_.get());
160                         GET_PROCADDR_FOR_FUNC(bfcRenderBufferCapture, h_module_.get());
161                         GET_PROCADDR_FOR_FUNC(bfcRenderBufferUpdate, h_module_.get());
162                         GET_PROCADDR_FOR_FUNC(bfcGetRenderBufferCount, h_module_.get());
163                         GET_PROCADDR_FOR_FUNC(bfcEncodeHancFrameEx, h_module_.get());
164                         GET_PROCADDR_FOR_FUNC(bfcDecodeHancFrameEx, h_module_.get());
165                         GET_PROCADDR_FOR_FUNC(bfcSystemBufferReadAsync, h_module_.get());
166                         GET_PROCADDR_FOR_FUNC(bfcSystemBufferWriteAsync, h_module_.get());
167                         GET_PROCADDR_FOR_FUNC(bfcGetBytesForGroupPixels, h_module_.get());
168                         GET_PROCADDR_FOR_FUNC(bfcGetPixelsPerLine, h_module_.get());
169                         GET_PROCADDR_FOR_FUNC(bfcGetLinesPerFrame, h_module_.get());
170                         GET_PROCADDR_FOR_FUNC(bfcGetBytesPerLine, h_module_.get());
171                         GET_PROCADDR_FOR_FUNC(bfcGetBytesPerFrame, h_module_.get());
172                         GET_PROCADDR_FOR_FUNC(bfcGetGoldenValue, h_module_.get());
173                         GET_PROCADDR_FOR_FUNC(bfcGetVBILines, h_module_.get());
174                         GET_PROCADDR_FOR_FUNC(bfcGetVANCGoldenValue, h_module_.get());
175                         GET_PROCADDR_FOR_FUNC(bfcGetVANCLineBytes, h_module_.get());
176                         GET_PROCADDR_FOR_FUNC(bfcGetVANCLineCount, h_module_.get());
177                         GET_PROCADDR_FOR_FUNC(bfcGetWindowsDriverHandle, h_module_.get());
178                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForCardType, h_module_.get());
179                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForBlueProductId, h_module_.get());
180                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForVideoMode, h_module_.get());
181                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForMemoryFormat, h_module_.get());
182                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetMR2Routing, h_module_.get());
183                         GET_PROCADDR_FOR_FUNC(bfcUtilsSetMR2Routing, h_module_.get());
184                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioOutputRouting, h_module_.get());
185                         GET_PROCADDR_FOR_FUNC(bfcUtilsSetAudioOutputRouting, h_module_.get());
186                         GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoModeProgressive, h_module_.get());
187                         GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoMode1001Framerate, h_module_.get());
188                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetFpsForVideoMode, h_module_.get());
189                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetVideoModeForFrameInfo, h_module_.get());
190                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetFrameInfoForVideoMode, h_module_.get());
191                         GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioSamplesPerFrame, h_module_.get());
192                         res = true;
193                 }
194                 return res;
195         }
196
197         const char * bvc_wrapper::get_version()
198         {
199                 return bfcGetVersion();
200         }
201
202         BLUE_UINT32 bvc_wrapper::attach(int iDeviceId)
203         {
204                 return bfcAttach((BLUEVELVETC_HANDLE)bvc_.get(), iDeviceId);
205         }
206
207         BLUE_UINT32 bvc_wrapper::detach()
208         {
209                 // disable the audio on detach
210                 unsigned int audio_value = 0;
211                 bfcQueryCardProperty32((BLUEVELVETC_HANDLE)bvc_.get(), EMBEDEDDED_AUDIO_OUTPUT, audio_value);
212                 return bfcDetach((BLUEVELVETC_HANDLE)bvc_.get());
213         }
214
215         BLUE_UINT32 bvc_wrapper::get_card_property32(const int iProperty, unsigned int & nValue)
216         {
217                 if (bvc_)
218                         return (BLUE_UINT32)bfcQueryCardProperty32((BLUEVELVETC_HANDLE)bvc_.get(), iProperty, nValue);
219                 else
220                         return 0;
221         }
222
223         BLUE_UINT32 bvc_wrapper::set_card_property32(const int iProperty, const unsigned int nValue)
224         {
225                 return bfcSetCardProperty32((BLUEVELVETC_HANDLE)bvc_.get(), iProperty, nValue);
226         }
227
228         BLUE_UINT32 bvc_wrapper::enumerate(int & iDevices)
229         {
230                 return bfcEnumerate((BLUEVELVETC_HANDLE)bvc_.get(), iDevices);
231         }
232
233         BLUE_UINT32 bvc_wrapper::query_card_type(int & iCardType, int iDeviceID)
234         {
235                 return bfcQueryCardType((BLUEVELVETC_HANDLE)bvc_.get(), iCardType, iDeviceID);
236         }
237
238         BLUE_UINT32 bvc_wrapper::system_buffer_write(unsigned char * pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset)
239         {
240                 return bfcSystemBufferWriteAsync((BLUEVELVETC_HANDLE)bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset);
241         }
242
243         BLUE_UINT32 bvc_wrapper::system_buffer_read(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset)
244         {
245                 return bfcSystemBufferReadAsync((BLUEVELVETC_HANDLE)bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset);
246         }
247
248         BLUE_UINT32 bvc_wrapper::video_playback_stop(int iWait, int iFlush)
249         {
250                 return bfcVideoPlaybackStop((BLUEVELVETC_HANDLE)bvc_.get(), iWait, iFlush);
251         }
252
253         BLUE_UINT32 bvc_wrapper::wait_video_output_sync(unsigned long ulUpdateType, unsigned long & ulFieldCount)
254         {
255                 return bfcWaitVideoOutputSync((BLUEVELVETC_HANDLE)bvc_.get(), ulUpdateType, ulFieldCount);
256         }
257
258         BLUE_UINT32 bvc_wrapper::wait_video_input_sync(unsigned long ulUpdateType, unsigned long & ulFieldCount)
259         {
260                 return bfcWaitVideoInputSync((BLUEVELVETC_HANDLE)bvc_.get(), ulUpdateType, ulFieldCount);
261         }
262
263         BLUE_UINT32 bvc_wrapper::render_buffer_update( unsigned long ulBufferID)
264         {
265                 return bfcRenderBufferUpdate((BLUEVELVETC_HANDLE)bvc_.get(), ulBufferID);
266         }
267
268         BLUE_UINT32 bvc_wrapper::render_buffer_capture(unsigned long ulBufferID)
269         {
270                 return bfcRenderBufferCapture((BLUEVELVETC_HANDLE)bvc_.get(), ulBufferID);
271         }
272
273         BLUE_UINT32 bvc_wrapper::encode_hanc_frame(unsigned int nCardType, hanc_stream_info_struct * pHancEncodeInfo, void * pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags)
274         {
275                 return bfcEncodeHancFrameEx((BLUEVELVETC_HANDLE)bvc_.get(), CRD_BLUE_NEUTRON, pHancEncodeInfo, pAudioBuffer, nAudioChannels, nAudioSamples, nSampleType, nAudioFlags);
276         }
277
278         BLUE_UINT32 bvc_wrapper::decode_hanc_frame(unsigned int nCardType, unsigned int * pHancBuffer, hanc_decode_struct * pHancDecodeInfo)
279         {
280                 return bfcDecodeHancFrameEx((BLUEVELVETC_HANDLE)bvc_.get(), CRD_BLUE_NEUTRON, pHancBuffer, pHancDecodeInfo);
281         }
282
283         BLUE_UINT32 bvc_wrapper::get_frame_info_for_video_mode(const unsigned int nVideoMode, unsigned int&  nWidth, unsigned int& nHeight, unsigned int& nRate, unsigned int& bIs1001, unsigned int& bIsProgressive)
284         {
285                 return bfcUtilsGetFrameInfoForVideoMode(nVideoMode, nWidth, nHeight, nRate, bIs1001, bIsProgressive);
286         }
287
288         BLUE_UINT32 bvc_wrapper::get_bytes_per_frame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame)
289         {
290                 return bfcGetBytesPerFrame(nVideoMode, nMemoryFormat, nUpdateMethod, nBytesPerFrame);
291         }
292
293
294 EVideoMode vid_fmt_from_video_format(const core::video_format& fmt) 
295 {
296         switch(fmt)
297         {
298         case core::video_format::pal:                   return VID_FMT_PAL;
299         case core::video_format::ntsc:                  return VID_FMT_NTSC;
300         case core::video_format::x576p2500:             return VID_FMT_INVALID; //not supported
301         case core::video_format::x720p2398:             return VID_FMT_720P_2398;
302         case core::video_format::x720p2400:             return VID_FMT_720P_2400;
303         case core::video_format::x720p2500:             return VID_FMT_720P_2500;
304         case core::video_format::x720p5000:             return VID_FMT_720P_5000;
305         case core::video_format::x720p2997:             return VID_FMT_720P_2997;
306         case core::video_format::x720p5994:             return VID_FMT_720P_5994;
307         case core::video_format::x720p3000:             return VID_FMT_720P_3000;
308         case core::video_format::x720p6000:             return VID_FMT_720P_6000;
309         case core::video_format::x1080p2398:    return VID_FMT_1080P_2397;
310         case core::video_format::x1080p2400:    return VID_FMT_1080P_2400;
311         case core::video_format::x1080i5000:    return VID_FMT_1080I_5000;
312         case core::video_format::x1080i5994:    return VID_FMT_1080I_5994;
313         case core::video_format::x1080i6000:    return VID_FMT_1080I_6000;
314         case core::video_format::x1080p2500:    return VID_FMT_1080P_2500;
315         case core::video_format::x1080p2997:    return VID_FMT_1080P_2997;
316         case core::video_format::x1080p3000:    return VID_FMT_1080P_3000;
317         case core::video_format::x1080p5000:    return VID_FMT_1080P_5000;
318         case core::video_format::x1080p5994:    return VID_FMT_1080P_5994;
319         case core::video_format::x1080p6000:    return VID_FMT_1080P_6000;
320         default:                                                                return VID_FMT_INVALID;
321         }
322 }
323
324 bool is_epoch_card(bvc_wrapper& blue)
325 {
326         int device_id = 1;
327         int card_type = 0;
328         blue.query_card_type(card_type, device_id);
329
330         switch(card_type)
331         {
332                 case CRD_BLUE_EPOCH_HORIZON:
333                 case CRD_BLUE_EPOCH_CORE:
334                 case CRD_BLUE_EPOCH_ULTRA:
335                 case CRD_BLUE_EPOCH_2K_HORIZON:
336                 case CRD_BLUE_EPOCH_2K_CORE:
337                 case CRD_BLUE_EPOCH_2K_ULTRA:
338                 case CRD_BLUE_CREATE_HD:
339                 case CRD_BLUE_CREATE_2K:
340                 case CRD_BLUE_CREATE_2K_ULTRA:
341                 case CRD_BLUE_SUPER_NOVA:
342                 case CRD_BLUE_SUPER_NOVA_S_PLUS:
343                 case CRD_BLUE_NEUTRON:
344                 case CRD_BLUE_EPOCH_CG:
345                 return true;
346         default:
347                 return false;
348         }
349 }
350
351 bool is_epoch_neutron_1i2o_card(bvc_wrapper& blue)
352 {
353         BLUE_UINT32 val = 0;
354         blue.get_card_property32(EPOCH_GET_PRODUCT_ID, val);
355         if (val == ORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID)
356                 return true;
357         else
358                 return false;
359 }
360
361 bool is_epoch_neutron_3o_card(bvc_wrapper& blue)
362 {
363         BLUE_UINT32 val = 0;
364         blue.get_card_property32(EPOCH_GET_PRODUCT_ID, val);
365
366         if (val == ORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID)
367                 return true;
368         else
369                 return false;
370 }
371
372 std::wstring get_card_desc(bvc_wrapper& blue, int device_id)
373 {
374         int card_type = 0;
375         blue.query_card_type(card_type, device_id);
376
377         switch(card_type)
378         {
379                 case CRD_BLUEDEEP_LT:                           return L"Deepblue LT";// D64 Lite
380                 case CRD_BLUEDEEP_SD:                           return L"Iridium SD";// Iridium SD
381                 case CRD_BLUEDEEP_AV:                           return L"Iridium AV";// Iridium AV
382                 case CRD_BLUEDEEP_IO:                           return L"Deepblue IO";// D64 Full
383                 case CRD_BLUEWILD_AV:                           return L"Wildblue AV";// D64 AV
384                 case CRD_IRIDIUM_HD:                            return L"Iridium HD";// * Iridium HD
385                 case CRD_BLUEWILD_RT:                           return L"Wildblue RT";// D64 RT
386                 case CRD_BLUEWILD_HD:                           return L"Wildblue HD";// * BadAss G2
387                 case CRD_REDDEVIL:                                      return L"Iridium Full";// Iridium Full
388                 case CRD_BLUEDEEP_HD:   
389                 case CRD_BLUEDEEP_HDS:                          return L"Reserved for \"BasAss G2";// * BadAss G2 variant, proposed, reserved
390                 case CRD_BLUE_ENVY:                                     return L"Blue Envy"; // Mini Din 
391                 case CRD_BLUE_PRIDE:                            return L"Blue Pride";//Mini Din Output 
392                 case CRD_BLUE_GREED:                            return L"Blue Greed";
393                 case CRD_BLUE_INGEST:                           return L"Blue Ingest";
394                 case CRD_BLUE_SD_DUALLINK:                      return L"Blue SD Duallink";
395                 case CRD_BLUE_CATALYST:                         return L"Blue Catalyst";
396                 case CRD_BLUE_SD_DUALLINK_PRO:          return L"Blue SD Duallink Pro";
397                 case CRD_BLUE_SD_INGEST_PRO:            return L"Blue SD Ingest pro";
398                 case CRD_BLUE_SD_DEEPBLUE_LITE_PRO:     return L"Blue SD Deepblue lite Pro";
399                 case CRD_BLUE_SD_SINGLELINK_PRO:        return L"Blue SD Singlelink Pro";
400                 case CRD_BLUE_SD_IRIDIUM_AV_PRO:        return L"Blue SD Iridium AV Pro";
401                 case CRD_BLUE_SD_FIDELITY:                      return L"Blue SD Fidelity";
402                 case CRD_BLUE_SD_FOCUS:                         return L"Blue SD Focus";
403                 case CRD_BLUE_SD_PRIME:                         return L"Blue SD Prime";
404                 case CRD_BLUE_EPOCH_2K_CORE:            return L"Blue Epoch 2K Core";
405                 case CRD_BLUE_EPOCH_2K_ULTRA:           return L"Blue Epoch 2K Ultra";
406                 case CRD_BLUE_EPOCH_HORIZON:            return L"Blue Epoch Horizon";
407                 case CRD_BLUE_EPOCH_CORE:                       return L"Blue Epoch Core";
408                 case CRD_BLUE_EPOCH_ULTRA:                      return L"Blue Epoch Ultra";
409                 case CRD_BLUE_CREATE_HD:                        return L"Blue Create HD";
410                 case CRD_BLUE_CREATE_2K:                        return L"Blue Create 2K";
411                 case CRD_BLUE_CREATE_2K_ULTRA:          return L"Blue Create 2K Ultra";
412                 case CRD_BLUE_SUPER_NOVA:                       return L"Blue SuperNova";
413                 case CRD_BLUE_SUPER_NOVA_S_PLUS:        return L"Blue SuperNova s+";
414                 case CRD_BLUE_NEUTRON:                          return L"Blue Neutron 4k";
415                 case CRD_BLUE_EPOCH_CG:                         return L"Blue Epopch CG";
416                 default:                                                        return L"Unknown";
417         }
418 }
419
420 EVideoMode get_video_mode(bvc_wrapper& blue, const core::video_format_desc& format_desc)
421 {
422         EVideoMode vid_fmt = VID_FMT_INVALID;
423         BLUE_UINT32 invalid_fmt = 0;
424         BErr err = 0;
425         err = blue.get_card_property32(INVALID_VIDEO_MODE_FLAG, invalid_fmt);
426         vid_fmt = vid_fmt_from_video_format(format_desc.format);
427
428         if (vid_fmt == VID_FMT_INVALID)
429                 CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported: " + format_desc.name));
430
431
432         if ((unsigned int)vid_fmt >= invalid_fmt)
433                 CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported - Outside of valid range: " + format_desc.name));
434
435         return vid_fmt;
436 }
437
438 spl::shared_ptr<bvc_wrapper> create_blue()
439 {
440         auto pWrap = new bvc_wrapper();
441         return spl::shared_ptr<bvc_wrapper>(pWrap);
442 }
443
444 spl::shared_ptr<bvc_wrapper> create_blue(int device_index)
445 {
446         auto blue = create_blue();
447         
448         if(BLUE_FAIL(blue->attach(device_index)))
449                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to attach device."));
450
451         return blue;
452 }
453
454 core::video_format video_format_from_vid_fmt(EVideoMode fmt)
455 {
456         switch (fmt)
457         {
458         case VID_FMT_PAL: return core::video_format::pal;
459         case VID_FMT_NTSC: return core::video_format::ntsc;
460         case VID_FMT_720P_2398: return core::video_format::x720p2398;
461         case VID_FMT_720P_2400: return core::video_format::x720p2400;
462         case VID_FMT_720P_2500: return core::video_format::x720p2500;
463         case VID_FMT_720P_5000: return core::video_format::x720p5000;
464         case VID_FMT_720P_2997: return core::video_format::x720p2997;
465         case VID_FMT_720P_5994: return core::video_format::x720p5994;
466         case VID_FMT_720P_3000: return core::video_format::x720p3000;
467         case VID_FMT_720P_6000: return core::video_format::x720p6000;
468         case VID_FMT_1080P_2397: return core::video_format::x1080p2398;
469         case VID_FMT_1080P_2400: return core::video_format::x1080p2400;
470         case VID_FMT_1080I_5000: return core::video_format::x1080i5000;
471         case VID_FMT_1080I_5994: return core::video_format::x1080i5994;
472         case VID_FMT_1080I_6000: return core::video_format::x1080i6000;
473         case VID_FMT_1080P_2500: return core::video_format::x1080p2500;
474         case VID_FMT_1080P_2997: return core::video_format::x1080p2997;
475         case VID_FMT_1080P_3000: return core::video_format::x1080p3000;
476         case VID_FMT_1080P_5000: return core::video_format::x1080p5000;
477         case VID_FMT_1080P_5994: return core::video_format::x1080p5994;
478         case VID_FMT_1080P_6000: return core::video_format::x1080p6000;
479         default: return core::video_format::invalid;
480         }
481 }
482
483 core::video_format_desc get_format_desc(bvc_wrapper& blue, EVideoMode vid_fmt, EMemoryFormat mem_fmt)
484 {
485         core::video_format_desc fmt;
486         unsigned int width, height, duration = 0, time_scale = 0, rate = 0, bIs1001 = 0, bIsProgressive = 0, size = 0;
487         std::vector<int>        audio_cadence;
488         core::field_mode video_field_mode = core::field_mode::progressive;
489
490         blue.get_frame_info_for_video_mode(vid_fmt, width, height, rate, bIs1001, bIsProgressive);
491         blue.get_bytes_per_frame(vid_fmt, mem_fmt, UPD_FMT_FRAME, size);
492
493         switch (vid_fmt)
494         {
495         case VID_FMT_NTSC:
496         case VID_FMT_1080I_5994:
497                 duration = 30000;
498                 time_scale = 1001;
499                 audio_cadence = { 1601,1602,1601,1602,1602 };
500                 video_field_mode = core::field_mode::upper;
501                 break;
502         case VID_FMT_2048_1080P_2500:
503         case VID_FMT_2048_1080PSF_2500:
504         case VID_FMT_576I_5000:
505         case VID_FMT_1080P_2500:
506         case VID_FMT_1080I_5000:
507         case VID_FMT_1080PSF_2500:
508         case VID_FMT_720P_2500:
509                 duration = 25000;
510                 time_scale = 1000;
511                 audio_cadence = { 1920,1920,1920,1920,1920 };
512                 break;
513
514         case VID_FMT_720P_5994:
515         case VID_FMT_2048_1080P_5994:
516         case VID_FMT_1080P_5994:
517                 duration = 60000;
518                 time_scale = 1001;
519                 audio_cadence = { 801,800,801,800,800 };
520                 break;
521
522         case VID_FMT_1080P_6000:
523         case VID_FMT_2048_1080P_6000:
524         case VID_FMT_720P_6000:
525                 duration = 60000;
526                 time_scale = 1000;
527                 audio_cadence = { 801,800,801,800,800 };
528                 break;
529
530         case VID_FMT_1080PSF_2397:
531         case VID_FMT_1080P_2397:
532         case VID_FMT_720P_2398:
533         case VID_FMT_2048_1080PSF_2397:
534         case VID_FMT_2048_1080P_2397:
535                 duration = 24000;
536                 time_scale = 1000;
537                 break;
538
539         case VID_FMT_1080PSF_2400:
540         case VID_FMT_1080P_2400:
541         case VID_FMT_720P_2400:
542         case VID_FMT_2048_1080PSF_2400:
543         case VID_FMT_2048_1080P_2400:
544                 duration = 24000;
545                 time_scale = 1000;
546                 break;
547
548         case VID_FMT_1080I_6000:
549         case VID_FMT_1080PSF_3000:
550                 duration = 30000;
551                 time_scale = 1000;
552                 break;
553
554         case VID_FMT_720P_2997:
555         case VID_FMT_1080P_2997:
556         case VID_FMT_2048_1080PSF_2997:
557         case VID_FMT_2048_1080P_2997:
558         case VID_FMT_1080PSF_2997:
559                 duration = 30000;
560                 time_scale = 1001;
561                 break;
562
563         case VID_FMT_720P_3000:
564         case VID_FMT_1080P_3000:
565         case VID_FMT_2048_1080PSF_3000:
566         case VID_FMT_2048_1080P_3000:
567                 duration = 30000;
568                 time_scale = 1001;
569                 break;
570
571         case VID_FMT_720P_5000:
572         case VID_FMT_1080P_5000:
573         case VID_FMT_2048_1080P_5000:
574                 audio_cadence = { 960,960,960,960,960 };
575                 duration = 50000;
576                 time_scale = 1000;
577                 break;
578                 /*case VID_FMT_1080P_4800:
579                 case VID_FMT_2048_1080P_4800:
580                 fmt.duration = 48000;
581                 fmt.time_scale = 1000;
582                 break;*/
583         }
584         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);
585         fmt.size = size;
586         return fmt;
587 }
588
589 }}