]> git.sesse.net Git - casparcg/blob - modules/decklink/util/util.h
Merged new video mode support from trunk
[casparcg] / modules / decklink / util / util.h
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 #pragma once
23
24 #include <common/except.h>
25 #include <common/log.h>
26 #include <core/video_format.h>
27
28 #include "../interop/DeckLinkAPI_h.h"
29
30 #include <boost/lexical_cast.hpp>
31
32 #include <atlbase.h>
33
34 #include <string>
35
36 namespace caspar { namespace decklink {
37         
38 static BMDDisplayMode get_decklink_video_format(core::video_format fmt) 
39 {
40         switch(fmt.value())
41         {
42         case core::video_format::pal:                   return bmdModePAL;
43         case core::video_format::ntsc:                  return bmdModeNTSC;
44         case core::video_format::x576p2500:             return (BMDDisplayMode)ULONG_MAX;
45         case core::video_format::x720p2398:             return (BMDDisplayMode)ULONG_MAX;
46         case core::video_format::x720p2400:             return (BMDDisplayMode)ULONG_MAX;
47         case core::video_format::x720p2500:             return (BMDDisplayMode)ULONG_MAX;
48         case core::video_format::x720p5000:             return bmdModeHD720p50;
49         case core::video_format::x720p2997:             return (BMDDisplayMode)ULONG_MAX;
50         case core::video_format::x720p5994:             return bmdModeHD720p5994;
51         case core::video_format::x720p3000:             return (BMDDisplayMode)ULONG_MAX;
52         case core::video_format::x720p6000:             return bmdModeHD720p60;
53         case core::video_format::x1080p2398:    return bmdModeHD1080p2398;
54         case core::video_format::x1080p2400:    return bmdModeHD1080p24;
55         case core::video_format::x1080i5000:    return bmdModeHD1080i50;
56         case core::video_format::x1080i5994:    return bmdModeHD1080i5994;
57         case core::video_format::x1080i6000:    return bmdModeHD1080i6000;
58         case core::video_format::x1080p2500:    return bmdModeHD1080p25;
59         case core::video_format::x1080p2997:    return bmdModeHD1080p2997;
60         case core::video_format::x1080p3000:    return bmdModeHD1080p30;
61         case core::video_format::x1080p5000:    return bmdModeHD1080p50;
62         case core::video_format::x1080p5994:    return bmdModeHD1080p5994;
63         case core::video_format::x1080p6000:    return bmdModeHD1080p6000;
64         default:                                                                return (BMDDisplayMode)ULONG_MAX;
65         }
66 }
67
68 static core::video_format get_caspar_video_format(BMDDisplayMode fmt) 
69 {
70         switch(fmt)
71         {
72         case bmdModePAL:                                                return core::video_format::pal;         
73         case bmdModeNTSC:                                               return core::video_format::ntsc;                
74         case bmdModeHD720p50:                                   return core::video_format::x720p5000;   
75         case bmdModeHD720p5994:                                 return core::video_format::x720p5994;   
76         case bmdModeHD720p60:                                   return core::video_format::x720p6000;   
77         case bmdModeHD1080p2398:                                return core::video_format::x1080p2398;  
78         case bmdModeHD1080p24:                                  return core::video_format::x1080p2400;  
79         case bmdModeHD1080i50:                                  return core::video_format::x1080i5000;  
80         case bmdModeHD1080i5994:                                return core::video_format::x1080i5994;  
81         case bmdModeHD1080i6000:                                return core::video_format::x1080i6000;  
82         case bmdModeHD1080p25:                                  return core::video_format::x1080p2500;
83         case bmdModeHD1080p2997:                                return core::video_format::x1080p2997;
84         case bmdModeHD1080p30:                                  return core::video_format::x1080p3000;
85         case bmdModeHD1080p50:                                  return core::video_format::x1080p5000;
86         case bmdModeHD1080p5994:                                return core::video_format::x1080p5994;
87         case bmdModeHD1080p6000:                                return core::video_format::x1080p6000;
88         default:                                                                return core::video_format::invalid;     
89         }
90 }
91
92 template<typename T, typename F>
93 BMDDisplayMode get_display_mode(const T& device, BMDDisplayMode format, BMDPixelFormat pix_fmt, F flag)
94 {
95         CComPtr<IDeckLinkDisplayModeIterator> iterator;
96         CComPtr<IDeckLinkDisplayMode>             mode;
97         
98         if(SUCCEEDED(device->GetDisplayModeIterator(&iterator)))
99         {
100                 while(SUCCEEDED(iterator->Next(&mode)) && 
101                                 mode != nullptr && 
102                                 mode->GetDisplayMode() != format){}
103         }
104
105         if(!mode)
106                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Device could not find requested video-format.") 
107                                                                                                  << arg_value_info(boost::lexical_cast<std::string>(format))
108                                                                                                  << arg_name_info("format"));
109                 
110         BMDDisplayModeSupport displayModeSupport;
111         if(FAILED(device->DoesSupportVideoMode(mode->GetDisplayMode(), pix_fmt, flag, &displayModeSupport, nullptr)) || displayModeSupport == bmdDisplayModeNotSupported)
112                 CASPAR_LOG(warning) << L"Device does not support video-format: " << mode->GetDisplayMode();
113                 //CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Device does not support requested video-format.")
114                 //                                                                               << arg_value_info(boost::lexical_cast<std::string>(format))
115                 //                                                                               << arg_name_info("format"));
116         else if(displayModeSupport == bmdDisplayModeSupportedWithConversion)
117                 CASPAR_LOG(warning) << L"Device supports video-format with conversion: " << mode->GetDisplayMode();
118
119         return mode->GetDisplayMode();
120 }
121
122 template<typename T, typename F>
123 static BMDDisplayMode get_display_mode(const T& device, core::video_format fmt, BMDPixelFormat pix_fmt, F flag)
124 {       
125         return get_display_mode(device, get_decklink_video_format(fmt), pix_fmt, flag);
126 }
127
128 template<typename T>
129 static std::wstring version(T& iterator)
130 {
131         CComQIPtr<IDeckLinkAPIInformation> info = iterator;
132         if (!info)
133                 return L"Unknown";
134         
135         BSTR ver;               
136         info->GetString(BMDDeckLinkAPIVersion, &ver);
137                 
138         return ver;                                     
139 }
140
141 static CComPtr<IDeckLink> get_device(size_t device_index)
142 {
143         CComPtr<IDeckLinkIterator> pDecklinkIterator;
144         if(FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))
145                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink drivers not found."));
146                 
147         size_t n = 0;
148         CComPtr<IDeckLink> decklink;
149         while(n < device_index && pDecklinkIterator->Next(&decklink) == S_OK){++n;}     
150
151         if(n != device_index || !decklink)
152                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Decklink device not found.") << arg_name_info("device_index") << arg_value_info(boost::lexical_cast<std::string>(device_index)));
153                 
154         return decklink;
155 }
156
157 template <typename T>
158 static std::wstring get_model_name(const T& device)
159 {       
160         BSTR pModelName;
161         device->GetModelName(&pModelName);
162         return std::wstring(pModelName);
163 }
164
165 }}