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