decklink: 59.94fps is 60000/1001, not 30000/1001
[platform/upstream/gstreamer.git] / sys / decklink / gstdecklink.cpp
1 /* GStreamer
2  * Copyright (C) 2011 David Schleef <ds@schleef.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17  * Boston, MA 02110-1335, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include "gstdecklink.h"
26 #include "gstdecklinksrc.h"
27 #include "gstdecklinksink.h"
28
29 GType
30 gst_decklink_mode_get_type (void)
31 {
32   static gsize id = 0;
33   static const GEnumValue modes[] = {
34     {GST_DECKLINK_MODE_NTSC, "ntsc", "NTSC SD 60i"},
35     {GST_DECKLINK_MODE_NTSC2398, "ntsc2398", "NTSC SD 60i (24 fps)"},
36     {GST_DECKLINK_MODE_PAL, "pal", "PAL SD 50i"},
37     {GST_DECKLINK_MODE_NTSC_P, "ntsc-p", "NTSC SD 60p"},
38     {GST_DECKLINK_MODE_PAL_P, "pal-p", "PAL SD 50p"},
39
40     {GST_DECKLINK_MODE_1080p2398, "1080p2398", "HD1080 23.98p"},
41     {GST_DECKLINK_MODE_1080p24, "1080p24", "HD1080 24p"},
42     {GST_DECKLINK_MODE_1080p25, "1080p25", "HD1080 25p"},
43     {GST_DECKLINK_MODE_1080p2997, "1080p2997", "HD1080 29.97p"},
44     {GST_DECKLINK_MODE_1080p30, "1080p30", "HD1080 30p"},
45
46     {GST_DECKLINK_MODE_1080i50, "1080i50", "HD1080 50i"},
47     {GST_DECKLINK_MODE_1080i5994, "1080i5994", "HD1080 59.94i"},
48     {GST_DECKLINK_MODE_1080i60, "1080i60", "HD1080 60i"},
49
50     {GST_DECKLINK_MODE_1080p50, "1080p50", "HD1080 50p"},
51     {GST_DECKLINK_MODE_1080p5994, "1080p5994", "HD1080 59.94p"},
52     {GST_DECKLINK_MODE_1080p60, "1080p60", "HD1080 60p"},
53
54     {GST_DECKLINK_MODE_720p50, "720p50", "HD720 50p"},
55     {GST_DECKLINK_MODE_720p5994, "720p5994", "HD720 59.94p"},
56     {GST_DECKLINK_MODE_720p60, "720p60", "HD720 60p"},
57
58     {0, NULL, NULL}
59   };
60
61   if (g_once_init_enter (&id)) {
62     GType tmp = g_enum_register_static ("GstDecklinkModes", modes);
63     g_once_init_leave (&id, tmp);
64   }
65
66   return (GType) id;
67 }
68
69 GType
70 gst_decklink_connection_get_type (void)
71 {
72   static gsize id = 0;
73   static const GEnumValue connections[] = {
74     {GST_DECKLINK_CONNECTION_SDI, "sdi", "SDI"},
75     {GST_DECKLINK_CONNECTION_HDMI, "hdmi", "HDMI"},
76     {GST_DECKLINK_CONNECTION_OPTICAL_SDI, "optical-sdi", "Optical SDI"},
77     {GST_DECKLINK_CONNECTION_COMPONENT, "component", "Component"},
78     {GST_DECKLINK_CONNECTION_COMPOSITE, "composite", "Composite"},
79     {GST_DECKLINK_CONNECTION_SVIDEO, "svideo", "S-Video"},
80     {0, NULL, NULL}
81   };
82
83   if (g_once_init_enter (&id)) {
84     GType tmp = g_enum_register_static ("GstDecklinkConnection", connections);
85     g_once_init_leave (&id, tmp);
86   }
87
88   return (GType) id;
89 }
90
91 GType
92 gst_decklink_audio_connection_get_type (void)
93 {
94   static gsize id = 0;
95   static const GEnumValue connections[] = {
96     {GST_DECKLINK_AUDIO_CONNECTION_AUTO, "auto", "Automatic"},
97     {GST_DECKLINK_AUDIO_CONNECTION_EMBEDDED, "embedded",
98         "SDI/HDMI embedded audio"},
99     {GST_DECKLINK_AUDIO_CONNECTION_AES_EBU, "aes", "AES/EBU input"},
100     {GST_DECKLINK_AUDIO_CONNECTION_ANALOG, "analog", "Analog input"},
101     {0, NULL, NULL}
102   };
103
104   if (g_once_init_enter (&id)) {
105     GType tmp =
106         g_enum_register_static ("GstDecklinkAudioConnection", connections);
107     g_once_init_leave (&id, tmp);
108   }
109
110   return (GType) id;
111 }
112
113 #define NTSC 10, 11, false, false
114 #define PAL 12, 11, true, false
115 #define HD 1, 1, false, true
116
117 static const GstDecklinkMode modes[] = {
118   {bmdModeNTSC, 720, 486, 30000, 1001, true, NTSC},
119   {bmdModeNTSC2398, 720, 486, 24000, 1001, true, NTSC},
120   {bmdModePAL, 720, 576, 25, 1, true, PAL},
121   {bmdModeNTSCp, 720, 486, 30000, 1001, false, NTSC},
122   {bmdModePALp, 720, 576, 25, 1, false, PAL},
123
124   {bmdModeHD1080p2398, 1920, 1080, 24000, 1001, false, HD},
125   {bmdModeHD1080p24, 1920, 1080, 24, 1, false, HD},
126   {bmdModeHD1080p25, 1920, 1080, 25, 1, false, HD},
127   {bmdModeHD1080p2997, 1920, 1080, 30000, 1001, false, HD},
128   {bmdModeHD1080p30, 1920, 1080, 30, 1, false, HD},
129
130   {bmdModeHD1080i50, 1920, 1080, 25, 1, true, HD},
131   {bmdModeHD1080i5994, 1920, 1080, 60000, 1001, true, HD},
132   {bmdModeHD1080i6000, 1920, 1080, 60, 1, true, HD},
133
134   {bmdModeHD1080p50, 1920, 1080, 50, 1, false, HD},
135   {bmdModeHD1080p5994, 1920, 1080, 60000, 1001, false, HD},
136   {bmdModeHD1080p6000, 1920, 1080, 60, 1, false, HD},
137
138   {bmdModeHD720p50, 1280, 720, 50, 1, false, HD},
139   {bmdModeHD720p5994, 1280, 720, 60000, 1001, false, HD},
140   {bmdModeHD720p60, 1280, 720, 60, 1, false, HD}
141
142 };
143
144 const GstDecklinkMode *
145 gst_decklink_get_mode (GstDecklinkModeEnum e)
146 {
147   return &modes[e];
148 }
149
150 static GstStructure *
151 gst_decklink_mode_get_structure (GstDecklinkModeEnum e)
152 {
153   const GstDecklinkMode *mode = &modes[e];
154
155   return gst_structure_new ("video/x-raw",
156       "format", G_TYPE_STRING, "UYVY",
157       "width", G_TYPE_INT, mode->width,
158       "height", G_TYPE_INT, mode->height,
159       "framerate", GST_TYPE_FRACTION, mode->fps_n, mode->fps_d,
160       "interlace-mode", G_TYPE_STRING, mode->interlaced ? "interleaved" : "progressive",
161       "pixel-aspect-ratio", GST_TYPE_FRACTION, mode->par_n, mode->par_d,
162       "colorimetry", G_TYPE_STRING, mode->is_hdtv ? "bt709" : "bt601",
163       "chroma-site", G_TYPE_STRING, "mpeg2", NULL);
164 }
165
166 GstCaps *
167 gst_decklink_mode_get_caps (GstDecklinkModeEnum e)
168 {
169   GstCaps *caps;
170
171   caps = gst_caps_new_empty ();
172   gst_caps_append_structure (caps, gst_decklink_mode_get_structure (e));
173
174   return caps;
175 }
176
177 GstCaps *
178 gst_decklink_mode_get_template_caps (void)
179 {
180   int i;
181   GstCaps *caps;
182   GstStructure *s;
183
184   caps = gst_caps_new_empty ();
185   for (i = 0; i < (int) G_N_ELEMENTS (modes); i++) {
186     s = gst_decklink_mode_get_structure ((GstDecklinkModeEnum) i);
187     gst_caps_append_structure (caps, s);
188   }
189
190   return caps;
191 }
192
193 typedef struct _Device Device;
194 struct _Device {
195   IDeckLink *decklink;
196   IDeckLinkInput *input;
197   IDeckLinkOutput *output;
198   IDeckLinkConfiguration *config;
199 };
200
201 static int n_devices;
202 static Device devices[10];
203
204 static void
205 init_devices (void)
206 {
207   IDeckLinkIterator *iterator;
208   IDeckLink *decklink = NULL;
209   HRESULT ret;
210   int i;
211   static gboolean inited = FALSE;
212
213   if (inited) return;
214   inited = TRUE;
215
216   iterator = CreateDeckLinkIteratorInstance ();
217   if (iterator == NULL) {
218     GST_ERROR ("no driver");
219     return;
220   }
221
222   i = 0;
223   ret = iterator->Next (&decklink);
224   while (ret == S_OK) {
225     devices[i].decklink = decklink;
226
227     ret = decklink->QueryInterface (IID_IDeckLinkInput,
228         (void **) &devices[i].input);
229     if (ret != S_OK) {
230       GST_WARNING ("selected device does not have input interface");
231     }
232
233     ret = decklink->QueryInterface (IID_IDeckLinkOutput,
234         (void **) &devices[i].output);
235     if (ret != S_OK) {
236       GST_WARNING ("selected device does not have output interface");
237     }
238
239     ret = decklink->QueryInterface (IID_IDeckLinkConfiguration,
240         (void **) &devices[i].config);
241     if (ret != S_OK) {
242       GST_WARNING ("selected device does not have config interface");
243     }
244
245     ret = iterator->Next (&decklink);
246     i++;
247
248     if (i == 10) {
249       GST_WARNING ("this hardware has more then 10 devices");
250       break;
251     }
252   }
253
254   n_devices = i;
255
256   iterator->Release();
257 }
258
259 IDeckLink *
260 gst_decklink_get_nth_device (int n)
261 {
262   init_devices ();
263   return devices[n].decklink;
264 }
265
266 IDeckLinkInput *
267 gst_decklink_get_nth_input (int n)
268 {
269   init_devices ();
270   return devices[n].input;
271 }
272
273 IDeckLinkOutput *
274 gst_decklink_get_nth_output (int n)
275 {
276   init_devices ();
277   return devices[n].output;
278 }
279
280 IDeckLinkConfiguration *
281 gst_decklink_get_nth_config (int n)
282 {
283   init_devices ();
284   return devices[n].config;
285 }
286
287 static gboolean
288 plugin_init (GstPlugin * plugin)
289 {
290
291   gst_element_register (plugin, "decklinksrc", GST_RANK_NONE,
292       gst_decklink_src_get_type ());
293
294   gst_element_register (plugin, "decklinksink", GST_RANK_NONE,
295       gst_decklink_sink_get_type ());
296
297   return TRUE;
298 }
299
300 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
301     GST_VERSION_MINOR,
302     decklink,
303     "Blackmagic Decklink plugin",
304     plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN)