]> git.sesse.net Git - casparcg/blob - modules/decklink/util/util.h
Add video modes 2160p5000, 2160p5994 and 2160p6000
[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 "../decklink_api.h"
29
30 #include <boost/lexical_cast.hpp>
31
32 #include <string>
33
34 namespace caspar { namespace decklink {
35         
36 static BMDDisplayMode get_decklink_video_format(core::video_format fmt) 
37 {
38         switch(fmt)
39         {
40         case core::video_format::pal:                   return bmdModePAL;
41         case core::video_format::ntsc:                  return bmdModeNTSC;
42         case core::video_format::x576p2500:             return (BMDDisplayMode)ULONG_MAX;
43         case core::video_format::x720p2398:             return (BMDDisplayMode)ULONG_MAX;
44         case core::video_format::x720p2400:             return (BMDDisplayMode)ULONG_MAX;
45         case core::video_format::x720p2500:             return (BMDDisplayMode)ULONG_MAX;
46         case core::video_format::x720p5000:             return bmdModeHD720p50;
47         case core::video_format::x720p2997:             return (BMDDisplayMode)ULONG_MAX;
48         case core::video_format::x720p5994:             return bmdModeHD720p5994;
49         case core::video_format::x720p3000:             return (BMDDisplayMode)ULONG_MAX;
50         case core::video_format::x720p6000:             return bmdModeHD720p60;
51         case core::video_format::x1080p2398:    return bmdModeHD1080p2398;
52         case core::video_format::x1080p2400:    return bmdModeHD1080p24;
53         case core::video_format::x1080i5000:    return bmdModeHD1080i50;
54         case core::video_format::x1080i5994:    return bmdModeHD1080i5994;
55         case core::video_format::x1080i6000:    return bmdModeHD1080i6000;
56         case core::video_format::x1080p2500:    return bmdModeHD1080p25;
57         case core::video_format::x1080p2997:    return bmdModeHD1080p2997;
58         case core::video_format::x1080p3000:    return bmdModeHD1080p30;
59         case core::video_format::x1080p5000:    return bmdModeHD1080p50;
60         case core::video_format::x1080p5994:    return bmdModeHD1080p5994;
61         case core::video_format::x1080p6000:    return bmdModeHD1080p6000;
62         case core::video_format::x1556p2398:    return bmdMode2k2398;
63         case core::video_format::x1556p2400:    return bmdMode2k24;
64         case core::video_format::x1556p2500:    return bmdMode2k25;
65         case core::video_format::dci1080p2398:  return bmdMode2kDCI2398;
66         case core::video_format::dci1080p2400:  return bmdMode2kDCI24;
67         case core::video_format::dci1080p2500:  return bmdMode2kDCI25;
68         case core::video_format::x2160p2398:    return bmdMode4K2160p2398;
69         case core::video_format::x2160p2400:    return bmdMode4K2160p24;
70         case core::video_format::x2160p2500:    return bmdMode4K2160p25;
71         case core::video_format::x2160p2997:    return bmdMode4K2160p2997;
72         case core::video_format::x2160p3000:    return bmdMode4K2160p30;
73         case core::video_format::x2160p5000:    return bmdMode4K2160p50;
74         case core::video_format::x2160p5994:    return bmdMode4K2160p5994;
75         case core::video_format::x2160p6000:    return bmdMode4K2160p60;
76         case core::video_format::dci2160p2398:  return bmdMode4kDCI2398;
77         case core::video_format::dci2160p2400:  return bmdMode4kDCI24;
78         case core::video_format::dci2160p2500:  return bmdMode4kDCI25;
79         default:                                                                return (BMDDisplayMode)ULONG_MAX;
80         }
81 }
82
83 static core::video_format get_caspar_video_format(BMDDisplayMode fmt) 
84 {
85         switch(fmt)
86         {
87         case bmdModePAL:                                                return core::video_format::pal;
88         case bmdModeNTSC:                                               return core::video_format::ntsc;
89         case bmdModeHD720p50:                                   return core::video_format::x720p5000;
90         case bmdModeHD720p5994:                                 return core::video_format::x720p5994;
91         case bmdModeHD720p60:                                   return core::video_format::x720p6000;
92         case bmdModeHD1080p2398:                                return core::video_format::x1080p2398;
93         case bmdModeHD1080p24:                                  return core::video_format::x1080p2400;
94         case bmdModeHD1080i50:                                  return core::video_format::x1080i5000;
95         case bmdModeHD1080i5994:                                return core::video_format::x1080i5994;
96         case bmdModeHD1080i6000:                                return core::video_format::x1080i6000;
97         case bmdModeHD1080p25:                                  return core::video_format::x1080p2500;
98         case bmdModeHD1080p2997:                                return core::video_format::x1080p2997;
99         case bmdModeHD1080p30:                                  return core::video_format::x1080p3000;
100         case bmdModeHD1080p50:                                  return core::video_format::x1080p5000;
101         case bmdModeHD1080p5994:                                return core::video_format::x1080p5994;
102         case bmdModeHD1080p6000:                                return core::video_format::x1080p6000;
103         case bmdMode2k2398:                                             return core::video_format::x1556p2398;
104         case bmdMode2k24:                                               return core::video_format::x1556p2400;
105         case bmdMode2k25:                                               return core::video_format::x1556p2500;
106         case bmdMode2kDCI2398:                                  return core::video_format::dci1080p2398;
107         case bmdMode2kDCI24:                                    return core::video_format::dci1080p2400;
108         case bmdMode2kDCI25:                                    return core::video_format::dci1080p2500;
109         case bmdMode4K2160p2398:                                return core::video_format::x2160p2398;
110         case bmdMode4K2160p24:                                  return core::video_format::x2160p2400;
111         case bmdMode4K2160p25:                                  return core::video_format::x2160p2500;
112         case bmdMode4K2160p2997:                                return core::video_format::x2160p2997;
113         case bmdMode4K2160p30:                                  return core::video_format::x2160p3000;
114         case bmdMode4K2160p50:                                  return core::video_format::x2160p5000;
115         case bmdMode4K2160p5994:                                return core::video_format::x2160p5994;
116         case bmdMode4K2160p60:                                  return core::video_format::x2160p6000;
117         case bmdMode4kDCI2398:                                  return core::video_format::dci2160p2398;
118         case bmdMode4kDCI24:                                    return core::video_format::dci2160p2400;
119         case bmdMode4kDCI25:                                    return core::video_format::dci2160p2500;
120         default:                                                                return core::video_format::invalid;
121         }
122 }
123
124 static std::wstring get_mode_name(const com_ptr<IDeckLinkDisplayMode>& mode)
125 {
126         String mode_name;
127         mode->GetName(&mode_name);
128         return u16(mode_name);
129 }
130
131 template<typename T, typename F>
132 BMDDisplayMode get_display_mode(const T& device, BMDDisplayMode format, BMDPixelFormat pix_fmt, F flag, bool& will_attempt_dma)
133 {
134     IDeckLinkDisplayMode* m = nullptr;
135     IDeckLinkDisplayModeIterator* iter;
136     if(SUCCEEDED(device->GetDisplayModeIterator(&iter)))
137         {
138         auto iterator = wrap_raw<com_ptr>(iter, true);
139         while(SUCCEEDED(iterator->Next(&m)) &&
140                 m != nullptr &&
141                 m->GetDisplayMode() != format)
142         {
143             m->Release();
144         }
145         }
146
147     if(!m)
148                 CASPAR_THROW_EXCEPTION(user_error() << msg_info("Device could not find requested video-format: " + boost::lexical_cast<std::string>(format)));
149
150         com_ptr<IDeckLinkDisplayMode> mode = wrap_raw<com_ptr>(m, true);
151
152         BMDDisplayModeSupport displayModeSupport;
153         will_attempt_dma = false;
154
155         if (FAILED(device->DoesSupportVideoMode(mode->GetDisplayMode(), pix_fmt, flag, &displayModeSupport, nullptr)))
156                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(L"Could not determine whether device supports requested video format: " + get_mode_name(mode)));
157         else if (displayModeSupport == bmdDisplayModeNotSupported)
158                 CASPAR_LOG(warning) << L"Device does not support video-format: " << get_mode_name(mode);
159         else if (displayModeSupport == bmdDisplayModeSupportedWithConversion)
160                 CASPAR_LOG(warning) << L"Device supports video-format with conversion: " << get_mode_name(mode);
161         else
162                 will_attempt_dma = true;
163
164         return mode->GetDisplayMode();
165 }
166
167 template<typename T, typename F>
168 static BMDDisplayMode get_display_mode(const T& device, core::video_format fmt, BMDPixelFormat pix_fmt, F flag, bool& will_attempt_dma)
169 {       
170         return get_display_mode(device, get_decklink_video_format(fmt), pix_fmt, flag, will_attempt_dma);
171 }
172
173 template<typename T>
174 static std::wstring version(T iterator)
175 {
176     auto info = iface_cast<IDeckLinkAPIInformation>(iterator);
177         if (!info)
178                 return L"Unknown";
179         
180     String ver;
181     info->GetString(BMDDeckLinkAPIVersion, &ver);
182                 
183     return u16(ver);
184 }
185
186 static com_ptr<IDeckLink> get_device(size_t device_index)
187 {
188     auto pDecklinkIterator = create_iterator();
189                 
190         size_t n = 0;
191     com_ptr<IDeckLink> decklink;
192     IDeckLink* current = nullptr;
193     while(n < device_index && pDecklinkIterator->Next(&current) == S_OK)
194     {
195         ++n;
196         decklink = wrap_raw<com_ptr>(current);
197         current->Release();
198     }
199
200         if(n != device_index || !decklink)
201                 CASPAR_THROW_EXCEPTION(user_error() << msg_info("Decklink device " + boost::lexical_cast<std::string>(device_index) + " not found."));
202                 
203         return decklink;
204 }
205
206 template <typename T>
207 static std::wstring get_model_name(const T& device)
208 {       
209     String pModelName;
210         device->GetModelName(&pModelName);
211     return u16(pModelName);
212 }
213
214 class reference_signal_detector
215 {
216         com_iface_ptr<IDeckLinkOutput>  output_;
217         BMDReferenceStatus                              last_reference_status_  = static_cast<BMDReferenceStatus>(-1);
218 public:
219         reference_signal_detector(const com_iface_ptr<IDeckLinkOutput>& output)
220                 : output_(output)
221         {
222         }
223
224         template<typename Print>
225         void detect_change(const Print& print)
226         {
227                 BMDReferenceStatus reference_status;
228
229                 if (output_->GetReferenceStatus(&reference_status) != S_OK)
230                 {
231                         CASPAR_LOG(error) << print() << L" Reference signal: failed while querying status";
232                 }
233                 else if (reference_status != last_reference_status_)
234                 {
235                         last_reference_status_ = reference_status;
236
237                         if (reference_status == 0)
238                                 CASPAR_LOG(info) << print() << L" Reference signal: not detected.";
239                         else if (reference_status & bmdReferenceNotSupportedByHardware)
240                                 CASPAR_LOG(info) << print() << L" Reference signal: not supported by hardware.";
241                         else if (reference_status & bmdReferenceLocked)
242                                 CASPAR_LOG(info) << print() << L" Reference signal: locked.";
243                         else
244                                 CASPAR_LOG(info) << print() << L" Reference signal: Unhandled enum bitfield: " << reference_status;
245                 }
246         }
247 };
248
249 }}