documentation: fixed a heap o' typos
[platform/upstream/gstreamer.git] / sys / decklink / gstdecklinkvideosrc.cpp
1 /* GStreamer
2  * Copyright (C) 2011 David Schleef <ds@entropywave.com>
3  * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
4  * Copyright (C) 2015 Florian Langlois <florian.langlois@fr.thalesgroup.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
19  * Boston, MA 02110-1335, USA.
20  */
21 /**
22  * SECTION:element-decklinkvideosrc
23  * @short_description: Inputs Video from a BlackMagic DeckLink Device
24  *
25  * Capture Video from a BlackMagic DeckLink Device.
26  *
27  * ## Sample pipeline
28  * |[
29  * gst-launch-1.0 \
30  *   decklinkvideosrc device-number=0 connection=sdi mode=1080p25 ! \
31  *   autovideosink
32  * ]|
33  * Capturing 1080p25 video from the SDI-In of Card 0. Devices are numbered
34  * starting with 0.
35  *
36  * # Duplex-Mode:
37  * Certain DechLink Cards like the Duo2 or the Quad2 contain two or four
38  * independent SDI units with two connectors each. These units can operate either
39  * in half- or in full-duplex mode.
40  *
41  * The Duplex-Mode of a Card can be configured using the `duplex-mode`-Property.
42  * Cards that to not support Duplex-Modes are not influenced by the property.
43  *
44  * ## Half-Duplex-Mode (default):
45  * By default decklinkvideosrc will configure them into half-duplex mode, so that
46  * each connector acts as if it were an independent DeckLink Card which can either
47  * be used as an Input or as an Output. In this mode the Duo2 can be used as as 4 SDI
48  * In-/Outputs and the Quad2 as 8 SDI In-/Outputs.
49  *
50  * |[
51  * gst-launch-1.0 \
52  *  decklinkvideosrc device-number=0 mode=1080p25 ! c. \
53  *  decklinkvideosrc device-number=1 mode=1080p25 ! c. \
54  *  decklinkvideosrc device-number=2 mode=1080p25 ! c. \
55  *  decklinkvideosrc device-number=3 mode=1080p25 ! c. \
56  *  compositor name=c \
57  *    sink_0::xpos=0   sink_0::ypos=0   sink_0::width=960 sink_0::height=540 \
58  *    sink_1::xpos=960 sink_1::ypos=0   sink_1::width=960 sink_1::height=540 \
59  *    sink_2::xpos=0   sink_2::ypos=540 sink_2::width=960 sink_2::height=540 \
60  *    sink_3::xpos=960 sink_3::ypos=540 sink_3::width=960 sink_3::height=540 ! \
61  *    video/x-raw,width=1920,height=1080 ! \
62  *    autovideosink
63  * ]|
64  * Capture 1080p25 from the first 4 units in the System (ie. the 4 Connectors of
65  * a Duo2 Card) and compose them into a 2x2 grid.
66  *
67  * |[
68  *  gst-launch-1.0 \
69  *    videotestsrc foreground-color=0x0000ff00 ! decklinkvideosink device-number=0 mode=1080p25 \
70  *    decklinkvideosrc device-number=1 mode=1080p25 ! autovideosink \
71  *    decklinkvideosrc device-number=2 mode=1080p25 ! autovideosink \
72  *    videotestsrc foreground-color=0x00ff0000 ! decklinkvideosink device-number=3 mode=1080p25
73  * ]|
74  * Capture 1080p25 from the second and third unit in the System,
75  * Playout a Test-Screen with colored Snow on the first and fourth unit
76  * (ie. the Connectors 1-4 of a Duo2 unit).
77  *
78  * ## Device-Number-Mapping in Half-Duplex-Mode
79  * The device-number to connector-mapping in half-duplex-mode is as follows for the Duo2
80  * - `device-number=0` SDI1
81  * - `device-number=1` SDI3
82  * - `device-number=2` SDI2
83  * - `device-number=3` SDI4
84  *
85  * And for the Quad2
86  * - `device-number=0` SDI1
87  * - `device-number=1` SDI3
88  * - `device-number=2` SDI5
89  * - `device-number=3` SDI7
90  * - `device-number=4` SDI2
91  * - `device-number=5` SDI4
92  * - `device-number=6` SDI6
93  * - `device-number=7` SDI8
94  *
95  * ## Full-Duplex-Mode:
96  * When operating in full-duplex mode, two connectors of a unit are combined to
97  * a single device, performing extra processing with the second connection.
98  *
99  * This mode is most useful for Playout. See @decklinkvideosink.
100  * For Capturing the options are as follows:
101  *
102  * When capturing from a duplex-unit, the secondary port outputs the captured image
103  * unchanged.
104  * |[
105  * gst-launch-1.0 \
106  *   decklinkvideosrc device-number=0 mode=1080p25 duplex-mode=full ! \
107  *   autovideosink
108  * ]|
109  *
110  * When simultaneously capturing and playing out onto the same device, the
111  * secondary port outputs the played out video. Note, that this can also be
112  * achieved using half-duplex mode.
113  * |[
114  * gst-launch-1.0 \
115  *   decklinkvideosrc device-number=0 mode=1080p25 duplex-mode=full ! \
116  *   videoflip video-direction=vert ! \
117  *   decklinkvideosink device-number=0 mode=1080p25 duplex-mode=full
118  * ]|
119  * Capturing Video on the primary port of device 0, output flipped version of the
120  * video on secondary port of the same device.
121  *
122  * ## Device-Number-Mapping in Full-Duplex-Mode
123  * The device-number to connector-mapping in full-duplex-mode is as follows for the Duo2
124  * - `device-number=0` SDI1 primary, SDI2 secondary
125  * - `device-number=1` SDI3 primaty, SDI4 secondary
126  *
127  * And for the Quad2
128  * - `device-number=0` SDI1 primary, SDI2 secondary
129  * - `device-number=1` SDI3 primaty, SDI4 secondary
130  * - `device-number=2` SDI5 primary, SDI6 secondary
131  * - `device-number=3` SDI7 primary, SDI8 secondary
132  */
133
134 #ifdef HAVE_CONFIG_H
135 #include "config.h"
136 #endif
137
138 #include "gstdecklinkvideosrc.h"
139 #include <string.h>
140
141 GST_DEBUG_CATEGORY_STATIC (gst_decklink_video_src_debug);
142 #define GST_CAT_DEFAULT gst_decklink_video_src_debug
143
144 #define DEFAULT_MODE (GST_DECKLINK_MODE_AUTO)
145 #define DEFAULT_CONNECTION (GST_DECKLINK_CONNECTION_AUTO)
146 #define DEFAULT_BUFFER_SIZE (5)
147 #define DEFAULT_OUTPUT_STREAM_TIME (FALSE)
148 #define DEFAULT_SKIP_FIRST_TIME (0)
149 #define DEFAULT_DROP_NO_SIGNAL_FRAMES (FALSE)
150 #define DEFAULT_OUTPUT_CC (FALSE)
151 #define DEFAULT_OUTPUT_AFD_BAR (FALSE)
152
153 #ifndef ABSDIFF
154 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
155 #endif
156
157 enum
158 {
159   PROP_0,
160   PROP_MODE,
161   PROP_CONNECTION,
162   PROP_DEVICE_NUMBER,
163   PROP_BUFFER_SIZE,
164   PROP_VIDEO_FORMAT,
165   PROP_DUPLEX_MODE,
166   PROP_TIMECODE_FORMAT,
167   PROP_OUTPUT_STREAM_TIME,
168   PROP_SKIP_FIRST_TIME,
169   PROP_DROP_NO_SIGNAL_FRAMES,
170   PROP_SIGNAL,
171   PROP_HW_SERIAL_NUMBER,
172   PROP_OUTPUT_CC,
173   PROP_OUTPUT_AFD_BAR,
174 };
175
176 typedef struct
177 {
178   IDeckLinkVideoInputFrame *frame;
179   GstClockTime timestamp, duration;
180   GstClockTime stream_timestamp;
181   GstClockTime stream_duration;
182   GstClockTime hardware_timestamp;
183   GstClockTime hardware_duration;
184   GstDecklinkModeEnum mode;
185   BMDPixelFormat format;
186   GstVideoTimeCode *tc;
187   gboolean no_signal;
188 } CaptureFrame;
189
190 static void
191 capture_frame_clear (CaptureFrame * frame)
192 {
193   if (frame->frame)
194     frame->frame->Release ();
195   if (frame->tc)
196     gst_video_time_code_free (frame->tc);
197   memset (frame, 0, sizeof (*frame));
198 }
199
200 typedef struct
201 {
202   IDeckLinkVideoInputFrame *frame;
203   IDeckLinkInput *input;
204 } VideoFrame;
205
206 static void
207 video_frame_free (void *data)
208 {
209   VideoFrame *frame = (VideoFrame *) data;
210
211   frame->frame->Release ();
212   frame->input->Release ();
213   g_free (frame);
214 }
215
216 static void gst_decklink_video_src_set_property (GObject * object,
217     guint property_id, const GValue * value, GParamSpec * pspec);
218 static void gst_decklink_video_src_get_property (GObject * object,
219     guint property_id, GValue * value, GParamSpec * pspec);
220 static void gst_decklink_video_src_finalize (GObject * object);
221
222 static GstStateChangeReturn
223 gst_decklink_video_src_change_state (GstElement * element,
224     GstStateChange transition);
225
226 static gboolean gst_decklink_video_src_query (GstBaseSrc * bsrc,
227     GstQuery * query);
228 static gboolean gst_decklink_video_src_unlock (GstBaseSrc * bsrc);
229 static gboolean gst_decklink_video_src_unlock_stop (GstBaseSrc * bsrc);
230
231 static GstFlowReturn gst_decklink_video_src_create (GstPushSrc * psrc,
232     GstBuffer ** buffer);
233
234 static gboolean gst_decklink_video_src_open (GstDecklinkVideoSrc * self);
235 static gboolean gst_decklink_video_src_close (GstDecklinkVideoSrc * self);
236
237 static gboolean gst_decklink_video_src_stop (GstDecklinkVideoSrc * self);
238
239 static void gst_decklink_video_src_start_streams (GstElement * element);
240
241 #define parent_class gst_decklink_video_src_parent_class
242 G_DEFINE_TYPE (GstDecklinkVideoSrc, gst_decklink_video_src, GST_TYPE_PUSH_SRC);
243
244 static void
245 gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass)
246 {
247   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
248   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
249   GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
250   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
251   GstCaps *templ_caps;
252
253   gobject_class->set_property = gst_decklink_video_src_set_property;
254   gobject_class->get_property = gst_decklink_video_src_get_property;
255   gobject_class->finalize = gst_decklink_video_src_finalize;
256
257   element_class->change_state =
258       GST_DEBUG_FUNCPTR (gst_decklink_video_src_change_state);
259
260   basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_video_src_query);
261   basesrc_class->negotiate = NULL;
262   basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock);
263   basesrc_class->unlock_stop =
264       GST_DEBUG_FUNCPTR (gst_decklink_video_src_unlock_stop);
265
266   pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_decklink_video_src_create);
267
268   g_object_class_install_property (gobject_class, PROP_MODE,
269       g_param_spec_enum ("mode", "Playback Mode",
270           "Video Mode to use for playback",
271           GST_TYPE_DECKLINK_MODE, DEFAULT_MODE,
272           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
273               G_PARAM_CONSTRUCT)));
274
275   g_object_class_install_property (gobject_class, PROP_CONNECTION,
276       g_param_spec_enum ("connection", "Connection",
277           "Video input connection to use",
278           GST_TYPE_DECKLINK_CONNECTION, DEFAULT_CONNECTION,
279           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
280               G_PARAM_CONSTRUCT)));
281
282   g_object_class_install_property (gobject_class, PROP_DEVICE_NUMBER,
283       g_param_spec_int ("device-number", "Device number",
284           "Output device instance to use", 0, G_MAXINT, 0,
285           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
286               G_PARAM_CONSTRUCT)));
287
288   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
289       g_param_spec_uint ("buffer-size", "Buffer Size",
290           "Size of internal buffer in number of video frames", 1,
291           G_MAXINT, DEFAULT_BUFFER_SIZE,
292           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
293
294   g_object_class_install_property (gobject_class, PROP_VIDEO_FORMAT,
295       g_param_spec_enum ("video-format", "Video format",
296           "Video format type to use for input (Only use auto for mode=auto)",
297           GST_TYPE_DECKLINK_VIDEO_FORMAT, GST_DECKLINK_VIDEO_FORMAT_AUTO,
298           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
299               G_PARAM_CONSTRUCT)));
300
301   g_object_class_install_property (gobject_class, PROP_DUPLEX_MODE,
302       g_param_spec_enum ("duplex-mode", "Duplex mode",
303           "Certain DeckLink devices such as the DeckLink Quad 2 and the "
304           "DeckLink Duo 2 support configuration of the duplex mode of "
305           "individual sub-devices."
306           "A sub-device configured as full-duplex will use two connectors, "
307           "which allows simultaneous capture and playback, internal keying, "
308           "and fill & key scenarios."
309           "A half-duplex sub-device will use a single connector as an "
310           "individual capture or playback channel.",
311           GST_TYPE_DECKLINK_DUPLEX_MODE, GST_DECKLINK_DUPLEX_MODE_HALF,
312           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
313               G_PARAM_CONSTRUCT)));
314
315   g_object_class_install_property (gobject_class, PROP_TIMECODE_FORMAT,
316       g_param_spec_enum ("timecode-format", "Timecode format",
317           "Timecode format type to use for input",
318           GST_TYPE_DECKLINK_TIMECODE_FORMAT,
319           GST_DECKLINK_TIMECODE_FORMAT_RP188ANY,
320           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
321               G_PARAM_CONSTRUCT)));
322
323   g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM_TIME,
324       g_param_spec_boolean ("output-stream-time", "Output Stream Time",
325           "Output stream time directly instead of translating to pipeline clock",
326           DEFAULT_OUTPUT_STREAM_TIME,
327           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
328
329   g_object_class_install_property (gobject_class, PROP_SKIP_FIRST_TIME,
330       g_param_spec_uint64 ("skip-first-time", "Skip First Time",
331           "Skip that much time of initial frames after starting", 0,
332           G_MAXUINT64, DEFAULT_SKIP_FIRST_TIME,
333           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
334
335   g_object_class_install_property (gobject_class, PROP_DROP_NO_SIGNAL_FRAMES,
336       g_param_spec_boolean ("drop-no-signal-frames", "Drop No Signal Frames",
337           "Drop frames that are marked as having no input signal",
338           DEFAULT_DROP_NO_SIGNAL_FRAMES,
339           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
340
341   g_object_class_install_property (gobject_class, PROP_SIGNAL,
342       g_param_spec_boolean ("signal", "Input signal available",
343           "True if there is a valid input signal available",
344           FALSE, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
345
346   g_object_class_install_property (gobject_class, PROP_HW_SERIAL_NUMBER,
347       g_param_spec_string ("hw-serial-number", "Hardware serial number",
348           "The serial number (hardware ID) of the Decklink card",
349           NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
350
351   g_object_class_install_property (gobject_class, PROP_OUTPUT_CC,
352       g_param_spec_boolean ("output-cc", "Output Closed Caption",
353           "Extract and output CC as GstMeta (if present)",
354           DEFAULT_OUTPUT_CC,
355           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
356
357   g_object_class_install_property (gobject_class, PROP_OUTPUT_AFD_BAR,
358       g_param_spec_boolean ("output-afd-bar", "Output AFD/Bar data",
359           "Extract and output AFD/Bar as GstMeta (if present)",
360           DEFAULT_OUTPUT_AFD_BAR,
361           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
362
363   templ_caps = gst_decklink_mode_get_template_caps (TRUE);
364   gst_element_class_add_pad_template (element_class,
365       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps));
366   gst_caps_unref (templ_caps);
367
368   gst_element_class_set_static_metadata (element_class, "Decklink Video Source",
369       "Video/Source/Hardware", "Decklink Source",
370       "David Schleef <ds@entropywave.com>, "
371       "Sebastian Dröge <sebastian@centricular.com>");
372
373   GST_DEBUG_CATEGORY_INIT (gst_decklink_video_src_debug, "decklinkvideosrc",
374       0, "debug category for decklinkvideosrc element");
375 }
376
377 static void
378 gst_decklink_video_src_init (GstDecklinkVideoSrc * self)
379 {
380   self->mode = DEFAULT_MODE;
381   self->caps_mode = GST_DECKLINK_MODE_AUTO;
382   self->caps_format = bmdFormat8BitYUV;
383   self->connection = DEFAULT_CONNECTION;
384   self->device_number = 0;
385   self->buffer_size = DEFAULT_BUFFER_SIZE;
386   self->video_format = GST_DECKLINK_VIDEO_FORMAT_AUTO;
387   self->duplex_mode = bmdDuplexModeHalf;
388   self->timecode_format = bmdTimecodeRP188Any;
389   self->signal_state = SIGNAL_STATE_UNKNOWN;
390   self->output_stream_time = DEFAULT_OUTPUT_STREAM_TIME;
391   self->skip_first_time = DEFAULT_SKIP_FIRST_TIME;
392   self->drop_no_signal_frames = DEFAULT_DROP_NO_SIGNAL_FRAMES;
393   self->output_cc = DEFAULT_OUTPUT_CC;
394   self->output_afd_bar = DEFAULT_OUTPUT_AFD_BAR;
395
396   self->window_size = 64;
397   self->times = g_new (GstClockTime, 4 * self->window_size);
398   self->times_temp = self->times + 2 * self->window_size;
399   self->window_fill = 0;
400   self->window_skip = 1;
401   self->window_skip_count = 0;
402
403   gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
404   gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
405
406   gst_pad_use_fixed_caps (GST_BASE_SRC_PAD (self));
407
408   g_mutex_init (&self->lock);
409   g_cond_init (&self->cond);
410
411   self->current_frames =
412       gst_queue_array_new_for_struct (sizeof (CaptureFrame),
413       DEFAULT_BUFFER_SIZE);
414 }
415
416 void
417 gst_decklink_video_src_set_property (GObject * object, guint property_id,
418     const GValue * value, GParamSpec * pspec)
419 {
420   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (object);
421
422   switch (property_id) {
423     case PROP_MODE:
424       self->mode = (GstDecklinkModeEnum) g_value_get_enum (value);
425       /* setting the default value for caps_mode here: if mode==auto then we
426        * configure caps_mode from the caps, if mode!=auto we set caps_mode to
427        * the same value as the mode. so self->caps_mode is essentially
428        * self->mode with mode=auto filtered into whatever we got from the
429        * negotiation */
430       if (self->mode != GST_DECKLINK_MODE_AUTO)
431         self->caps_mode = self->mode;
432       break;
433     case PROP_CONNECTION:
434       self->connection = (GstDecklinkConnectionEnum) g_value_get_enum (value);
435       break;
436     case PROP_DEVICE_NUMBER:
437       self->device_number = g_value_get_int (value);
438       break;
439     case PROP_BUFFER_SIZE:
440       self->buffer_size = g_value_get_uint (value);
441       break;
442     case PROP_VIDEO_FORMAT:
443       self->video_format = (GstDecklinkVideoFormat) g_value_get_enum (value);
444       switch (self->video_format) {
445         case GST_DECKLINK_VIDEO_FORMAT_8BIT_YUV:
446         case GST_DECKLINK_VIDEO_FORMAT_10BIT_YUV:
447         case GST_DECKLINK_VIDEO_FORMAT_8BIT_ARGB:
448         case GST_DECKLINK_VIDEO_FORMAT_8BIT_BGRA:
449           self->caps_format =
450               gst_decklink_pixel_format_from_type (self->video_format);
451         case GST_DECKLINK_VIDEO_FORMAT_AUTO:
452           break;
453         default:
454           GST_ELEMENT_WARNING (GST_ELEMENT (self), CORE, NOT_IMPLEMENTED,
455               ("Format %d not supported", self->video_format), (NULL));
456           break;
457       }
458       break;
459     case PROP_DUPLEX_MODE:
460       self->duplex_mode =
461           gst_decklink_duplex_mode_from_enum ((GstDecklinkDuplexMode)
462           g_value_get_enum (value));
463       break;
464     case PROP_TIMECODE_FORMAT:
465       self->timecode_format =
466           gst_decklink_timecode_format_from_enum ((GstDecklinkTimecodeFormat)
467           g_value_get_enum (value));
468       break;
469     case PROP_OUTPUT_STREAM_TIME:
470       self->output_stream_time = g_value_get_boolean (value);
471       break;
472     case PROP_SKIP_FIRST_TIME:
473       self->skip_first_time = g_value_get_uint64 (value);
474       break;
475     case PROP_DROP_NO_SIGNAL_FRAMES:
476       self->drop_no_signal_frames = g_value_get_boolean (value);
477       break;
478     case PROP_OUTPUT_CC:
479       self->output_cc = g_value_get_boolean (value);
480       break;
481     case PROP_OUTPUT_AFD_BAR:
482       self->output_afd_bar = g_value_get_boolean (value);
483       break;
484     default:
485       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
486       break;
487   }
488 }
489
490 void
491 gst_decklink_video_src_get_property (GObject * object, guint property_id,
492     GValue * value, GParamSpec * pspec)
493 {
494   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (object);
495
496   switch (property_id) {
497     case PROP_MODE:
498       g_value_set_enum (value, self->mode);
499       break;
500     case PROP_CONNECTION:
501       g_value_set_enum (value, self->connection);
502       break;
503     case PROP_DEVICE_NUMBER:
504       g_value_set_int (value, self->device_number);
505       break;
506     case PROP_BUFFER_SIZE:
507       g_value_set_uint (value, self->buffer_size);
508       break;
509     case PROP_VIDEO_FORMAT:
510       g_value_set_enum (value, self->video_format);
511       break;
512     case PROP_DUPLEX_MODE:
513       g_value_set_enum (value,
514           gst_decklink_duplex_mode_to_enum (self->duplex_mode));
515       break;
516     case PROP_TIMECODE_FORMAT:
517       g_value_set_enum (value,
518           gst_decklink_timecode_format_to_enum (self->timecode_format));
519       break;
520     case PROP_OUTPUT_STREAM_TIME:
521       g_value_set_boolean (value, self->output_stream_time);
522       break;
523     case PROP_SKIP_FIRST_TIME:
524       g_value_set_uint64 (value, self->skip_first_time);
525       break;
526     case PROP_DROP_NO_SIGNAL_FRAMES:
527       g_value_set_boolean (value, self->drop_no_signal_frames);
528       break;
529     case PROP_SIGNAL:
530       g_value_set_boolean (value, self->signal_state == SIGNAL_STATE_AVAILABLE);
531       break;
532     case PROP_HW_SERIAL_NUMBER:
533       if (self->input)
534         g_value_set_string (value, self->input->hw_serial_number);
535       else
536         g_value_set_string (value, NULL);
537       break;
538     case PROP_OUTPUT_CC:
539       g_value_set_boolean (value, self->output_cc);
540       break;
541     case PROP_OUTPUT_AFD_BAR:
542       g_value_set_boolean (value, self->output_afd_bar);
543       break;
544     default:
545       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
546       break;
547   }
548 }
549
550 void
551 gst_decklink_video_src_finalize (GObject * object)
552 {
553   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (object);
554
555   g_free (self->times);
556   self->times = NULL;
557   g_mutex_clear (&self->lock);
558   g_cond_clear (&self->cond);
559
560   if (self->current_frames) {
561     while (gst_queue_array_get_length (self->current_frames) > 0) {
562       CaptureFrame *tmp = (CaptureFrame *)
563           gst_queue_array_pop_head_struct (self->current_frames);
564       capture_frame_clear (tmp);
565     }
566     gst_queue_array_free (self->current_frames);
567     self->current_frames = NULL;
568   }
569
570   G_OBJECT_CLASS (parent_class)->finalize (object);
571 }
572
573 static gboolean
574 gst_decklink_video_src_start (GstDecklinkVideoSrc * self)
575 {
576   const GstDecklinkMode *mode;
577   BMDVideoInputFlags flags;
578   HRESULT ret;
579   BMDPixelFormat format;
580
581   g_mutex_lock (&self->input->lock);
582   if (self->input->video_enabled) {
583     g_mutex_unlock (&self->input->lock);
584     return TRUE;
585   }
586   g_mutex_unlock (&self->input->lock);
587
588   if (self->input->config && self->connection != GST_DECKLINK_CONNECTION_AUTO) {
589     ret = self->input->config->SetInt (bmdDeckLinkConfigVideoInputConnection,
590         gst_decklink_get_connection (self->connection));
591     if (ret != S_OK) {
592       GST_ERROR_OBJECT (self,
593           "Failed to set configuration (input source): 0x%08lx",
594           (unsigned long) ret);
595       return FALSE;
596     }
597
598     if (self->connection == GST_DECKLINK_CONNECTION_COMPOSITE) {
599       ret = self->input->config->SetInt (bmdDeckLinkConfigAnalogVideoInputFlags,
600           bmdAnalogVideoFlagCompositeSetup75);
601       if (ret != S_OK) {
602         GST_ERROR_OBJECT (self,
603             "Failed to set configuration (composite setup): 0x%08lx",
604             (unsigned long) ret);
605         return FALSE;
606       }
607     }
608   }
609
610   flags = bmdVideoInputFlagDefault;
611   if (self->mode == GST_DECKLINK_MODE_AUTO) {
612     bool autoDetection = false;
613
614     if (self->input->attributes) {
615       ret =
616           self->input->
617           attributes->GetFlag (BMDDeckLinkSupportsInputFormatDetection,
618           &autoDetection);
619       if (ret != S_OK) {
620         GST_ERROR_OBJECT (self,
621             "Failed to get attribute (autodetection): 0x%08lx",
622             (unsigned long) ret);
623         return FALSE;
624       }
625       if (autoDetection)
626         flags |= bmdVideoInputEnableFormatDetection;
627     }
628     if (!autoDetection) {
629       GST_ERROR_OBJECT (self, "Failed to activate auto-detection");
630       return FALSE;
631     }
632   }
633
634   mode = gst_decklink_get_mode (self->mode);
635   g_assert (mode != NULL);
636
637   format = self->caps_format;
638   ret = self->input->input->EnableVideoInput (mode->mode, format, flags);
639   if (ret != S_OK) {
640     GST_WARNING_OBJECT (self, "Failed to enable video input: 0x%08lx",
641         (unsigned long) ret);
642     return FALSE;
643   }
644
645   g_mutex_lock (&self->input->lock);
646   self->input->mode = mode;
647   self->input->video_enabled = TRUE;
648   if (self->input->start_streams)
649     self->input->start_streams (self->input->videosrc);
650   g_mutex_unlock (&self->input->lock);
651
652   return TRUE;
653 }
654
655 static void
656 gst_decklink_video_src_update_time_mapping (GstDecklinkVideoSrc * self,
657     GstClockTime capture_time, GstClockTime stream_time)
658 {
659   if (self->window_skip_count == 0) {
660     GstClockTime num, den, b, xbase;
661     gdouble r_squared;
662
663     self->times[2 * self->window_fill] = stream_time;
664     self->times[2 * self->window_fill + 1] = capture_time;
665
666     self->window_fill++;
667     self->window_skip_count++;
668     if (self->window_skip_count >= self->window_skip)
669       self->window_skip_count = 0;
670
671     if (self->window_fill >= self->window_size) {
672       guint fps =
673           ((gdouble) self->info.fps_n + self->info.fps_d -
674           1) / ((gdouble) self->info.fps_d);
675
676       /* Start by updating first every frame, once full every second frame,
677        * etc. until we update once every 4 seconds */
678       if (self->window_skip < 4 * fps)
679         self->window_skip *= 2;
680       if (self->window_skip >= 4 * fps)
681         self->window_skip = 4 * fps;
682
683       self->window_fill = 0;
684       self->window_filled = TRUE;
685     }
686
687     /* First sample ever, create some basic mapping to start */
688     if (!self->window_filled && self->window_fill == 1) {
689       self->current_time_mapping.xbase = stream_time;
690       self->current_time_mapping.b = capture_time;
691       self->current_time_mapping.num = 1;
692       self->current_time_mapping.den = 1;
693       self->next_time_mapping_pending = FALSE;
694     }
695
696     /* Only bother calculating anything here once we had enough measurements,
697      * i.e. let's take the window size as a start */
698     if (self->window_filled &&
699         gst_calculate_linear_regression (self->times, self->times_temp,
700             self->window_size, &num, &den, &b, &xbase, &r_squared)) {
701
702       GST_DEBUG_OBJECT (self,
703           "Calculated new time mapping: pipeline time = %lf * (stream time - %"
704           G_GUINT64_FORMAT ") + %" G_GUINT64_FORMAT " (%lf)",
705           ((gdouble) num) / ((gdouble) den), xbase, b, r_squared);
706
707       self->next_time_mapping.xbase = xbase;
708       self->next_time_mapping.b = b;
709       self->next_time_mapping.num = num;
710       self->next_time_mapping.den = den;
711       self->next_time_mapping_pending = TRUE;
712     }
713   } else {
714     self->window_skip_count++;
715     if (self->window_skip_count >= self->window_skip)
716       self->window_skip_count = 0;
717   }
718
719   if (self->next_time_mapping_pending) {
720     GstClockTime expected, new_calculated, diff, max_diff;
721
722     expected =
723         gst_clock_adjust_with_calibration (NULL, stream_time,
724         self->current_time_mapping.xbase, self->current_time_mapping.b,
725         self->current_time_mapping.num, self->current_time_mapping.den);
726     new_calculated =
727         gst_clock_adjust_with_calibration (NULL, stream_time,
728         self->next_time_mapping.xbase, self->next_time_mapping.b,
729         self->next_time_mapping.num, self->next_time_mapping.den);
730
731     if (new_calculated > expected)
732       diff = new_calculated - expected;
733     else
734       diff = expected - new_calculated;
735
736     /* At most 5% frame duration change per update */
737     max_diff =
738         gst_util_uint64_scale (GST_SECOND / 20, self->info.fps_d,
739         self->info.fps_n);
740
741     GST_DEBUG_OBJECT (self,
742         "New time mapping causes difference of %" GST_TIME_FORMAT,
743         GST_TIME_ARGS (diff));
744     GST_DEBUG_OBJECT (self, "Maximum allowed per frame %" GST_TIME_FORMAT,
745         GST_TIME_ARGS (max_diff));
746
747     if (diff > max_diff) {
748       /* adjust so that we move that much closer */
749       if (new_calculated > expected) {
750         self->current_time_mapping.b = expected + max_diff;
751         self->current_time_mapping.xbase = stream_time;
752       } else {
753         self->current_time_mapping.b = expected - max_diff;
754         self->current_time_mapping.xbase = stream_time;
755       }
756     } else {
757       self->current_time_mapping.xbase = self->next_time_mapping.xbase;
758       self->current_time_mapping.b = self->next_time_mapping.b;
759       self->current_time_mapping.num = self->next_time_mapping.num;
760       self->current_time_mapping.den = self->next_time_mapping.den;
761       self->next_time_mapping_pending = FALSE;
762     }
763   }
764 }
765
766 static void
767 gst_decklink_video_src_got_frame (GstElement * element,
768     IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
769     GstClockTime capture_time, GstClockTime stream_time,
770     GstClockTime stream_duration, GstClockTime hardware_time,
771     GstClockTime hardware_duration, IDeckLinkTimecode * dtc, gboolean no_signal)
772 {
773   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
774   GstClockTime timestamp, duration;
775
776   GST_LOG_OBJECT (self,
777       "Got video frame at %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT " (%"
778       GST_TIME_FORMAT "), no signal: %d", GST_TIME_ARGS (capture_time),
779       GST_TIME_ARGS (stream_time), GST_TIME_ARGS (stream_duration), no_signal);
780
781   g_mutex_lock (&self->lock);
782   if (self->first_time == GST_CLOCK_TIME_NONE)
783     self->first_time = stream_time;
784
785   if (self->skip_first_time > 0
786       && stream_time - self->first_time < self->skip_first_time) {
787     g_mutex_unlock (&self->lock);
788     GST_DEBUG_OBJECT (self,
789         "Skipping frame as requested: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT,
790         GST_TIME_ARGS (stream_time),
791         GST_TIME_ARGS (self->skip_first_time + self->first_time));
792     return;
793   }
794
795   if (self->drop_no_signal_frames && no_signal) {
796     CaptureFrame f;
797     memset (&f, 0, sizeof (f));
798
799     /* Notify the streaming thread about the signal loss */
800     gst_queue_array_push_tail_struct (self->current_frames, &f);
801     g_cond_signal (&self->cond);
802     g_mutex_unlock (&self->lock);
803
804     return;
805   }
806
807   gst_decklink_video_src_update_time_mapping (self, capture_time, stream_time);
808   if (self->output_stream_time) {
809     timestamp = stream_time;
810     duration = stream_duration;
811   } else {
812     timestamp =
813         gst_clock_adjust_with_calibration (NULL, stream_time,
814         self->current_time_mapping.xbase, self->current_time_mapping.b,
815         self->current_time_mapping.num, self->current_time_mapping.den);
816     duration =
817         gst_util_uint64_scale (stream_duration, self->current_time_mapping.num,
818         self->current_time_mapping.den);
819   }
820
821   GST_LOG_OBJECT (self,
822       "Converted times to %" GST_TIME_FORMAT " (%"
823       GST_TIME_FORMAT ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
824
825   if (!self->flushing) {
826     CaptureFrame f;
827     const GstDecklinkMode *bmode;
828     GstVideoTimeCodeFlags flags = GST_VIDEO_TIME_CODE_FLAGS_NONE;
829     guint field_count = 0;
830     guint skipped_frames = 0;
831     GstClockTime from_timestamp = GST_CLOCK_TIME_NONE;
832     GstClockTime to_timestamp = GST_CLOCK_TIME_NONE;
833
834     while (gst_queue_array_get_length (self->current_frames) >=
835         self->buffer_size) {
836       CaptureFrame *tmp = (CaptureFrame *)
837           gst_queue_array_pop_head_struct (self->current_frames);
838       if (tmp->frame) {
839         if (skipped_frames == 0)
840           from_timestamp = tmp->timestamp;
841         skipped_frames++;
842         to_timestamp = tmp->timestamp;
843       }
844       capture_frame_clear (tmp);
845     }
846
847     if (skipped_frames > 0)
848       GST_WARNING_OBJECT (self,
849           "Dropped %u old frames from %" GST_TIME_FORMAT " to %"
850           GST_TIME_FORMAT, skipped_frames, GST_TIME_ARGS (from_timestamp),
851           GST_TIME_ARGS (to_timestamp));
852
853     memset (&f, 0, sizeof (f));
854     f.frame = frame;
855     f.timestamp = timestamp;
856     f.duration = duration;
857     f.stream_timestamp = stream_time;
858     f.stream_duration = stream_duration;
859     f.hardware_timestamp = hardware_time;
860     f.hardware_duration = hardware_duration;
861     f.mode = mode;
862     f.format = frame->GetPixelFormat ();
863     f.no_signal = no_signal;
864     if (dtc != NULL) {
865       uint8_t hours, minutes, seconds, frames;
866       HRESULT res;
867
868       res = dtc->GetComponents (&hours, &minutes, &seconds, &frames);
869       if (res != S_OK) {
870         GST_ERROR ("Could not get components for timecode %p: 0x%08lx", dtc,
871             (unsigned long) res);
872         f.tc = NULL;
873       } else {
874         GST_DEBUG_OBJECT (self, "Got timecode %02d:%02d:%02d:%02d",
875             hours, minutes, seconds, frames);
876         bmode = gst_decklink_get_mode (mode);
877         if (bmode->interlaced)
878           flags =
879               (GstVideoTimeCodeFlags) (flags |
880               GST_VIDEO_TIME_CODE_FLAGS_INTERLACED);
881         if (bmode->fps_d == 1001) {
882           if (bmode->fps_n == 30000 || bmode->fps_n == 60000) {
883             /* Some occurrences have been spotted where the driver mistakenly
884              * fails to set the drop-frame flag for drop-frame timecodes.
885              * Assume always drop-frame for 29.97 and 59.94 FPS */
886             flags =
887                 (GstVideoTimeCodeFlags) (flags |
888                 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME);
889           } else {
890             /* Drop-frame isn't defined for any other framerates (e.g. 23.976)
891              * */
892             flags =
893                 (GstVideoTimeCodeFlags) (flags &
894                 ~GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME);
895           }
896         }
897         f.tc =
898             gst_video_time_code_new (bmode->fps_n, bmode->fps_d, NULL, flags,
899             hours, minutes, seconds, frames, field_count);
900       }
901       dtc->Release ();
902     } else {
903       f.tc = NULL;
904     }
905
906     frame->AddRef ();
907     gst_queue_array_push_tail_struct (self->current_frames, &f);
908     g_cond_signal (&self->cond);
909   }
910   g_mutex_unlock (&self->lock);
911 }
912
913 static void
914 extract_vbi_line (GstDecklinkVideoSrc * self, GstBuffer ** buffer,
915     IDeckLinkVideoFrameAncillary * vanc_frame, guint field2_offset, guint line,
916     gboolean * found_cc_out, gboolean * found_afd_bar_out)
917 {
918   GstVideoAncillary gstanc;
919   const guint8 *vancdata;
920   gboolean found_cc = FALSE, found_afd_bar = FALSE;
921
922   if (vanc_frame->GetBufferForVerticalBlankingLine (field2_offset + line,
923           (void **) &vancdata) != S_OK)
924     return;
925
926   GST_DEBUG_OBJECT (self, "Checking for VBI data on field line %u (field %u)",
927       field2_offset + line, field2_offset ? 2 : 1);
928   gst_video_vbi_parser_add_line (self->vbiparser, vancdata);
929
930   /* Check if CC or AFD/Bar is on this line if we didn't find any on a
931    * previous line. Remember the line where we found them */
932
933   while (gst_video_vbi_parser_get_ancillary (self->vbiparser,
934           &gstanc) == GST_VIDEO_VBI_PARSER_RESULT_OK) {
935     switch (GST_VIDEO_ANCILLARY_DID16 (&gstanc)) {
936       case GST_VIDEO_ANCILLARY_DID16_S334_EIA_708:
937         if (*found_cc_out || !self->output_cc)
938           continue;
939
940         GST_DEBUG_OBJECT (self,
941             "Adding CEA-708 CDP meta to buffer for line %u",
942             field2_offset + line);
943         GST_MEMDUMP_OBJECT (self, "CDP", gstanc.data, gstanc.data_count);
944         gst_buffer_add_video_caption_meta (*buffer,
945             GST_VIDEO_CAPTION_TYPE_CEA708_CDP, gstanc.data, gstanc.data_count);
946
947         found_cc = TRUE;
948         if (field2_offset)
949           self->last_cc_vbi_line_field2 = line;
950         else
951           self->last_cc_vbi_line = line;
952         break;
953       case GST_VIDEO_ANCILLARY_DID16_S334_EIA_608:
954         if (*found_cc_out || !self->output_cc)
955           continue;
956
957         GST_DEBUG_OBJECT (self,
958             "Adding CEA-608 meta to buffer for line %u", field2_offset + line);
959         GST_MEMDUMP_OBJECT (self, "CEA608", gstanc.data, gstanc.data_count);
960         gst_buffer_add_video_caption_meta (*buffer,
961             GST_VIDEO_CAPTION_TYPE_CEA608_S334_1A, gstanc.data,
962             gstanc.data_count);
963
964         found_cc = TRUE;
965         if (field2_offset)
966           self->last_cc_vbi_line_field2 = line;
967         else
968           self->last_cc_vbi_line = line;
969         break;
970       case GST_VIDEO_ANCILLARY_DID16_S2016_3_AFD_BAR:{
971         GstVideoAFDValue afd;
972         gboolean is_letterbox;
973         guint16 bar1, bar2;
974
975         if (*found_afd_bar_out || !self->output_afd_bar)
976           continue;
977
978         GST_DEBUG_OBJECT (self,
979             "Adding AFD/Bar meta to buffer for line %u", field2_offset + line);
980         GST_MEMDUMP_OBJECT (self, "AFD/Bar", gstanc.data, gstanc.data_count);
981
982         if (gstanc.data_count < 16) {
983           GST_WARNING_OBJECT (self, "AFD/Bar data too small");
984           continue;
985         }
986
987         afd = (GstVideoAFDValue) ((gstanc.data[0] >> 3) & 0xf);
988         is_letterbox = ((gstanc.data[3] >> 4) & 0x3) == 0;
989         bar1 = GST_READ_UINT16_BE (&gstanc.data[4]);
990         bar2 = GST_READ_UINT16_BE (&gstanc.data[6]);
991
992         gst_buffer_add_video_afd_meta (*buffer, field2_offset ? 1 : 0,
993             GST_VIDEO_AFD_SPEC_SMPTE_ST2016_1, afd);
994         gst_buffer_add_video_bar_meta (*buffer, field2_offset ? 1 : 0,
995             is_letterbox, bar1, bar2);
996
997         found_afd_bar = TRUE;
998         if (field2_offset)
999           self->last_afd_bar_vbi_line_field2 = line;
1000         else
1001           self->last_afd_bar_vbi_line = line;
1002         break;
1003       }
1004       default:
1005         /* otherwise continue looking */
1006         continue;
1007     }
1008   }
1009
1010   if (found_cc)
1011     *found_cc_out = TRUE;
1012   if (found_afd_bar)
1013     *found_afd_bar_out = TRUE;
1014 }
1015
1016 static void
1017 extract_vbi (GstDecklinkVideoSrc * self, GstBuffer ** buffer, VideoFrame * vf)
1018 {
1019   IDeckLinkVideoFrameAncillary *vanc_frame = NULL;
1020   gint line;
1021   GstVideoFormat videoformat;
1022   GstDecklinkModeEnum mode_enum;
1023   const GstDecklinkMode *mode;
1024   gboolean found_cc = FALSE, found_afd_bar = FALSE;
1025
1026   if (vf->frame->GetAncillaryData (&vanc_frame) != S_OK)
1027     return;
1028
1029   videoformat =
1030       gst_decklink_video_format_from_type (vanc_frame->GetPixelFormat ());
1031   mode_enum =
1032       gst_decklink_get_mode_enum_from_bmd (vanc_frame->GetDisplayMode ());
1033   mode = gst_decklink_get_mode (mode_enum);
1034
1035   if (videoformat == GST_VIDEO_FORMAT_UNKNOWN) {
1036     GST_DEBUG_OBJECT (self, "Unknown video format for Ancillary data");
1037     vanc_frame->Release ();
1038     return;
1039   }
1040
1041   if ((videoformat != self->anc_vformat || mode->width != self->anc_width)
1042       && self->vbiparser) {
1043     gst_video_vbi_parser_free (self->vbiparser);
1044     self->vbiparser = NULL;
1045   }
1046
1047   if (self->vbiparser == NULL) {
1048     self->vbiparser = gst_video_vbi_parser_new (videoformat, mode->width);
1049     self->anc_vformat = videoformat;
1050     self->anc_width = mode->width;
1051   }
1052
1053   GST_DEBUG_OBJECT (self, "Checking for ancillary data in VBI");
1054
1055   /* First check last known lines, if any */
1056   if (self->last_cc_vbi_line > 0) {
1057     extract_vbi_line (self, buffer, vanc_frame, 0, self->last_cc_vbi_line,
1058         &found_cc, &found_afd_bar);
1059   }
1060   if (self->last_afd_bar_vbi_line > 0
1061       && self->last_cc_vbi_line != self->last_afd_bar_vbi_line) {
1062     extract_vbi_line (self, buffer, vanc_frame, 0, self->last_afd_bar_vbi_line,
1063         &found_cc, &found_afd_bar);
1064   }
1065
1066   if (!found_cc)
1067     self->last_cc_vbi_line = -1;
1068   if (!found_afd_bar)
1069     self->last_afd_bar_vbi_line = -1;
1070
1071   if ((self->output_cc && !found_cc) || (self->output_afd_bar
1072           && !found_afd_bar)) {
1073     /* Otherwise loop through the first 21 lines and hope to find the data */
1074     /* FIXME: For the different formats the number of lines that can contain
1075      * VANC are different */
1076     for (line = 1; line < 22; line++) {
1077       extract_vbi_line (self, buffer, vanc_frame, 0, line, &found_cc,
1078           &found_afd_bar);
1079
1080       /* If we found everything we wanted to extract, stop here */
1081       if ((!self->output_cc || found_cc) &&
1082           (!self->output_afd_bar || found_afd_bar))
1083         break;
1084     }
1085   }
1086
1087   /* Do the same for field 2 in case of interlaced content */
1088   if (GST_VIDEO_INFO_IS_INTERLACED (&self->info)) {
1089     gboolean found_cc_field2 = FALSE, found_afd_bar_field2 = FALSE;
1090     guint field2_offset = 0;
1091
1092     /* The VANC lines for the second field are at an offset, depending on
1093      * the format in use
1094      */
1095     switch (self->info.height) {
1096       case 486:
1097         /* NTSC: 525 / 2 + 1 */
1098         field2_offset = 263;
1099         break;
1100       case 576:
1101         /* PAL: 625 / 2 + 1 */
1102         field2_offset = 313;
1103         break;
1104       case 1080:
1105         /* 1080i: 1125 / 2 + 1 */
1106         field2_offset = 563;
1107         break;
1108       default:
1109         g_assert_not_reached ();
1110     }
1111
1112     /* First try the same lines as for field 1 if we don't know yet */
1113     if (self->last_cc_vbi_line_field2 <= 0)
1114       self->last_cc_vbi_line_field2 = self->last_cc_vbi_line;
1115     if (self->last_afd_bar_vbi_line_field2 <= 0)
1116       self->last_afd_bar_vbi_line_field2 = self->last_afd_bar_vbi_line;
1117
1118     if (self->last_cc_vbi_line_field2 > 0) {
1119       extract_vbi_line (self, buffer, vanc_frame, field2_offset,
1120           self->last_cc_vbi_line_field2, &found_cc_field2,
1121           &found_afd_bar_field2);
1122     }
1123     if (self->last_afd_bar_vbi_line_field2 > 0
1124         && self->last_cc_vbi_line_field2 !=
1125         self->last_afd_bar_vbi_line_field2) {
1126       extract_vbi_line (self, buffer, vanc_frame, field2_offset,
1127           self->last_afd_bar_vbi_line_field2, &found_cc_field2,
1128           &found_afd_bar_field2);
1129     }
1130
1131     if (!found_cc_field2)
1132       self->last_cc_vbi_line_field2 = -1;
1133     if (!found_afd_bar_field2)
1134       self->last_afd_bar_vbi_line_field2 = -1;
1135
1136     if (((self->output_cc && !found_cc_field2) || (self->output_afd_bar
1137                 && !found_afd_bar_field2))) {
1138       for (line = 1; line < 22; line++) {
1139         extract_vbi_line (self, buffer, vanc_frame, field2_offset, line,
1140             &found_cc_field2, &found_afd_bar_field2);
1141
1142         /* If we found everything we wanted to extract, stop here */
1143         if ((!self->output_cc || found_cc_field2) &&
1144             (!self->output_afd_bar || found_afd_bar_field2))
1145           break;
1146       }
1147     }
1148   }
1149
1150   vanc_frame->Release ();
1151 }
1152
1153 static GstFlowReturn
1154 gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
1155 {
1156   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
1157   GstFlowReturn flow_ret = GST_FLOW_OK;
1158   const guint8 *data;
1159   gsize data_size;
1160   VideoFrame *vf;
1161   CaptureFrame f;
1162   GstCaps *caps;
1163   gboolean caps_changed = FALSE;
1164   const GstDecklinkMode *mode;
1165   static GstStaticCaps stream_reference =
1166       GST_STATIC_CAPS ("timestamp/x-decklink-stream");
1167   static GstStaticCaps hardware_reference =
1168       GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
1169
1170   if (!gst_decklink_video_src_start (self)) {
1171     return GST_FLOW_NOT_NEGOTIATED;
1172   }
1173
1174   g_mutex_lock (&self->lock);
1175 retry:
1176   while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) {
1177     g_cond_wait (&self->cond, &self->lock);
1178   }
1179
1180   if (self->flushing) {
1181     GST_DEBUG_OBJECT (self, "Flushing");
1182     g_mutex_unlock (&self->lock);
1183     return GST_FLOW_FLUSHING;
1184   }
1185
1186   f = *(CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
1187
1188   // We will have no frame if frames without signal are dropped immediately
1189   // but we still have to signal that it's lost here.
1190   if (f.no_signal || !f.frame) {
1191     if (self->signal_state != SIGNAL_STATE_LOST) {
1192       self->signal_state = SIGNAL_STATE_LOST;
1193       g_object_notify (G_OBJECT (self), "signal");
1194       GST_ELEMENT_WARNING (GST_ELEMENT (self), RESOURCE, READ, ("Signal lost"),
1195           ("No input source was detected - video frames invalid"));
1196     }
1197     // If we have no frame here, simply retry until we got one
1198     if (!f.frame) {
1199       capture_frame_clear (&f);
1200       goto retry;
1201     }
1202   } else {
1203     GstDecklinkSignalState previous_signal_state = self->signal_state;
1204
1205     if (previous_signal_state != SIGNAL_STATE_AVAILABLE) {
1206       self->signal_state = SIGNAL_STATE_AVAILABLE;
1207       g_object_notify (G_OBJECT (self), "signal");
1208     }
1209
1210     if (previous_signal_state == SIGNAL_STATE_LOST) {
1211       GST_ELEMENT_INFO (GST_ELEMENT (self), RESOURCE, READ,
1212           ("Signal recovered"), ("Input source detected"));
1213     }
1214   }
1215
1216   // If we're not flushing, we should have a valid frame from the queue
1217   g_assert (f.frame != NULL);
1218
1219   if (!gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
1220     caps_changed = TRUE;
1221   }
1222
1223   if (self->caps_mode != f.mode) {
1224     if (self->mode == GST_DECKLINK_MODE_AUTO
1225         || !gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
1226       GST_DEBUG_OBJECT (self, "Mode changed from %d to %d", self->caps_mode,
1227           f.mode);
1228       caps_changed = TRUE;
1229       self->caps_mode = f.mode;
1230     } else {
1231       g_mutex_unlock (&self->lock);
1232       GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
1233           ("Invalid mode in captured frame"),
1234           ("Mode set to %d but captured %d", self->caps_mode, f.mode));
1235       capture_frame_clear (&f);
1236       return GST_FLOW_NOT_NEGOTIATED;
1237     }
1238   }
1239   if (self->caps_format != f.format) {
1240     if (self->video_format == GST_DECKLINK_VIDEO_FORMAT_AUTO
1241         || !gst_pad_has_current_caps (GST_BASE_SRC_PAD (self))) {
1242       GST_DEBUG_OBJECT (self, "Format changed from %d to %d", self->caps_format,
1243           f.format);
1244       caps_changed = TRUE;
1245       self->caps_format = f.format;
1246     } else {
1247       g_mutex_unlock (&self->lock);
1248       GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
1249           ("Invalid pixel format in captured frame"),
1250           ("Format set to %d but captured %d", self->caps_format, f.format));
1251       capture_frame_clear (&f);
1252       return GST_FLOW_NOT_NEGOTIATED;
1253     }
1254   }
1255
1256   /* 1 ns error can be just a rounding error, so that's OK. The Decklink
1257    * drivers give us a really steady stream time, so anything above 1 ns can't
1258    * be a rounding error and is therefore something to worry about */
1259   if (self->expected_stream_time != GST_CLOCK_TIME_NONE &&
1260       ABSDIFF (self->expected_stream_time, f.stream_timestamp) > 1) {
1261     GstMessage *msg;
1262     GstClockTime running_time;
1263
1264     self->dropped += f.stream_timestamp - self->expected_stream_time;
1265     running_time = gst_segment_to_running_time (&GST_BASE_SRC (self)->segment,
1266         GST_FORMAT_TIME, f.timestamp);
1267
1268     msg =
1269         gst_message_new_qos (GST_OBJECT (self), TRUE, running_time,
1270         f.stream_timestamp, f.timestamp, f.duration);
1271     gst_message_set_qos_stats (msg, GST_FORMAT_TIME, self->processed,
1272         self->dropped);
1273     gst_element_post_message (GST_ELEMENT (self), msg);
1274   }
1275   if (self->first_stream_time == GST_CLOCK_TIME_NONE)
1276     self->first_stream_time = f.stream_timestamp;
1277   self->processed =
1278       f.stream_timestamp - self->dropped - self->first_stream_time;
1279   self->expected_stream_time = f.stream_timestamp + f.stream_duration;
1280
1281   g_mutex_unlock (&self->lock);
1282   if (caps_changed) {
1283     self->last_cc_vbi_line = -1;
1284     self->last_afd_bar_vbi_line = -1;
1285     self->last_cc_vbi_line_field2 = -1;
1286     self->last_afd_bar_vbi_line_field2 = -1;
1287     caps = gst_decklink_mode_get_caps (f.mode, f.format, TRUE);
1288     gst_video_info_from_caps (&self->info, caps);
1289     gst_base_src_set_caps (GST_BASE_SRC_CAST (bsrc), caps);
1290     gst_element_post_message (GST_ELEMENT_CAST (self),
1291         gst_message_new_latency (GST_OBJECT_CAST (self)));
1292     gst_caps_unref (caps);
1293     if (self->vbiparser) {
1294       gst_video_vbi_parser_free (self->vbiparser);
1295       self->vbiparser = NULL;
1296       self->anc_vformat = GST_VIDEO_FORMAT_UNKNOWN;
1297       self->anc_width = 0;
1298     }
1299   }
1300
1301   f.frame->GetBytes ((gpointer *) & data);
1302   data_size = self->info.size;
1303
1304   vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));
1305
1306   *buffer =
1307       gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
1308       (gpointer) data, data_size, 0, data_size, vf,
1309       (GDestroyNotify) video_frame_free);
1310
1311   vf->frame = f.frame;
1312   f.frame->AddRef ();
1313   vf->input = self->input->input;
1314   vf->input->AddRef ();
1315
1316   // If we have a format that supports VANC and we are asked to extract CC,
1317   // then do it here.
1318   if ((self->output_cc || self->output_afd_bar)
1319       && self->signal_state != SIGNAL_STATE_LOST)
1320     extract_vbi (self, buffer, vf);
1321
1322   if (f.no_signal)
1323     GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_GAP);
1324   GST_BUFFER_TIMESTAMP (*buffer) = f.timestamp;
1325   GST_BUFFER_DURATION (*buffer) = f.duration;
1326   if (f.tc != NULL)
1327     gst_buffer_add_video_time_code_meta (*buffer, f.tc);
1328   gst_buffer_add_reference_timestamp_meta (*buffer,
1329       gst_static_caps_get (&stream_reference), f.stream_timestamp,
1330       f.stream_duration);
1331   gst_buffer_add_reference_timestamp_meta (*buffer,
1332       gst_static_caps_get (&hardware_reference), f.hardware_timestamp,
1333       f.hardware_duration);
1334
1335   mode = gst_decklink_get_mode (self->caps_mode);
1336   if (mode->interlaced && mode->tff)
1337     GST_BUFFER_FLAG_SET (*buffer,
1338         GST_VIDEO_BUFFER_FLAG_TFF | GST_VIDEO_BUFFER_FLAG_INTERLACED);
1339   else if (mode->interlaced)
1340     GST_BUFFER_FLAG_SET (*buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
1341
1342   GST_DEBUG_OBJECT (self,
1343       "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
1344       GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)),
1345       GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer)));
1346
1347   capture_frame_clear (&f);
1348
1349   return flow_ret;
1350 }
1351
1352 static gboolean
1353 gst_decklink_video_src_query (GstBaseSrc * bsrc, GstQuery * query)
1354 {
1355   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
1356   gboolean ret = TRUE;
1357
1358   switch (GST_QUERY_TYPE (query)) {
1359     case GST_QUERY_LATENCY:{
1360       if (self->input) {
1361         GstClockTime min, max;
1362         const GstDecklinkMode *mode;
1363
1364         g_mutex_lock (&self->lock);
1365         mode = gst_decklink_get_mode (self->caps_mode);
1366         g_mutex_unlock (&self->lock);
1367
1368         min = gst_util_uint64_scale_ceil (GST_SECOND, mode->fps_d, mode->fps_n);
1369         max = self->buffer_size * min;
1370
1371         gst_query_set_latency (query, TRUE, min, max);
1372         ret = TRUE;
1373       } else {
1374         ret = FALSE;
1375       }
1376
1377       break;
1378     }
1379     default:
1380       ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1381       break;
1382   }
1383
1384   return ret;
1385 }
1386
1387 static gboolean
1388 gst_decklink_video_src_unlock (GstBaseSrc * bsrc)
1389 {
1390   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
1391
1392   g_mutex_lock (&self->lock);
1393   self->flushing = TRUE;
1394   g_cond_signal (&self->cond);
1395   g_mutex_unlock (&self->lock);
1396
1397   return TRUE;
1398 }
1399
1400 static gboolean
1401 gst_decklink_video_src_unlock_stop (GstBaseSrc * bsrc)
1402 {
1403   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (bsrc);
1404
1405   g_mutex_lock (&self->lock);
1406   self->flushing = FALSE;
1407   while (gst_queue_array_get_length (self->current_frames) > 0) {
1408     CaptureFrame *tmp =
1409         (CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
1410     capture_frame_clear (tmp);
1411   }
1412   g_mutex_unlock (&self->lock);
1413
1414   return TRUE;
1415 }
1416
1417 static gboolean
1418 gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
1419 {
1420   const GstDecklinkMode *mode;
1421
1422   GST_DEBUG_OBJECT (self, "Opening");
1423
1424   self->input =
1425       gst_decklink_acquire_nth_input (self->device_number,
1426       GST_ELEMENT_CAST (self), FALSE);
1427   if (!self->input) {
1428     GST_ERROR_OBJECT (self, "Failed to acquire input");
1429     return FALSE;
1430   }
1431
1432   g_object_notify (G_OBJECT (self), "hw-serial-number");
1433
1434   mode = gst_decklink_get_mode (self->mode);
1435   g_assert (mode != NULL);
1436   g_mutex_lock (&self->input->lock);
1437   self->input->mode = mode;
1438   self->input->format = self->caps_format;
1439   self->input->got_video_frame = gst_decklink_video_src_got_frame;
1440   self->input->start_streams = gst_decklink_video_src_start_streams;
1441   g_mutex_unlock (&self->input->lock);
1442
1443   return TRUE;
1444 }
1445
1446 static gboolean
1447 gst_decklink_video_src_close (GstDecklinkVideoSrc * self)
1448 {
1449
1450   GST_DEBUG_OBJECT (self, "Closing");
1451
1452   if (self->input) {
1453     g_mutex_lock (&self->input->lock);
1454     self->input->got_video_frame = NULL;
1455     self->input->mode = NULL;
1456     self->input->video_enabled = FALSE;
1457     self->input->start_streams = NULL;
1458     g_mutex_unlock (&self->input->lock);
1459
1460     gst_decklink_release_nth_input (self->device_number,
1461         GST_ELEMENT_CAST (self), FALSE);
1462     self->input = NULL;
1463   }
1464
1465   return TRUE;
1466 }
1467
1468 static gboolean
1469 gst_decklink_video_src_stop (GstDecklinkVideoSrc * self)
1470 {
1471   GST_DEBUG_OBJECT (self, "Stopping");
1472
1473   while (gst_queue_array_get_length (self->current_frames) > 0) {
1474     CaptureFrame *tmp =
1475         (CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
1476     capture_frame_clear (tmp);
1477   }
1478   self->caps_mode = GST_DECKLINK_MODE_AUTO;
1479
1480   if (self->input && self->input->video_enabled) {
1481     g_mutex_lock (&self->input->lock);
1482     self->input->video_enabled = FALSE;
1483     g_mutex_unlock (&self->input->lock);
1484
1485     self->input->input->DisableVideoInput ();
1486   }
1487
1488   if (self->vbiparser) {
1489     gst_video_vbi_parser_free (self->vbiparser);
1490     self->vbiparser = NULL;
1491     self->anc_vformat = GST_VIDEO_FORMAT_UNKNOWN;
1492     self->anc_width = 0;
1493   }
1494
1495   return TRUE;
1496 }
1497
1498 static void
1499 gst_decklink_video_src_start_streams (GstElement * element)
1500 {
1501   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
1502   HRESULT res;
1503
1504   if (self->input->video_enabled && (!self->input->audiosrc
1505           || self->input->audio_enabled)
1506       && (GST_STATE (self) == GST_STATE_PLAYING
1507           || GST_STATE_PENDING (self) == GST_STATE_PLAYING)) {
1508     GST_DEBUG_OBJECT (self, "Starting streams");
1509
1510     g_mutex_lock (&self->lock);
1511     self->first_time = GST_CLOCK_TIME_NONE;
1512     self->window_fill = 0;
1513     self->window_filled = FALSE;
1514     self->window_skip = 1;
1515     self->window_skip_count = 0;
1516     self->current_time_mapping.xbase = 0;
1517     self->current_time_mapping.b = 0;
1518     self->current_time_mapping.num = 1;
1519     self->current_time_mapping.den = 1;
1520     self->next_time_mapping.xbase = 0;
1521     self->next_time_mapping.b = 0;
1522     self->next_time_mapping.num = 1;
1523     self->next_time_mapping.den = 1;
1524     g_mutex_unlock (&self->lock);
1525     res = self->input->input->StartStreams ();
1526     if (res != S_OK) {
1527       GST_ELEMENT_ERROR (self, STREAM, FAILED,
1528           (NULL), ("Failed to start streams: 0x%08lx", (unsigned long) res));
1529       return;
1530     }
1531   } else {
1532     GST_DEBUG_OBJECT (self, "Not starting streams yet");
1533   }
1534 }
1535
1536 static GstStateChangeReturn
1537 gst_decklink_video_src_change_state (GstElement * element,
1538     GstStateChange transition)
1539 {
1540   GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
1541   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1542
1543   switch (transition) {
1544     case GST_STATE_CHANGE_NULL_TO_READY:
1545       self->processed = 0;
1546       self->dropped = 0;
1547       self->expected_stream_time = GST_CLOCK_TIME_NONE;
1548       self->first_stream_time = GST_CLOCK_TIME_NONE;
1549       if (!gst_decklink_video_src_open (self)) {
1550         ret = GST_STATE_CHANGE_FAILURE;
1551         goto out;
1552       }
1553       if (self->mode == GST_DECKLINK_MODE_AUTO &&
1554           self->video_format != GST_DECKLINK_VIDEO_FORMAT_AUTO) {
1555         GST_WARNING_OBJECT (self, "Warning: mode=auto and format!=auto may \
1556                             not work");
1557       }
1558       self->vbiparser = NULL;
1559       self->anc_vformat = GST_VIDEO_FORMAT_UNKNOWN;
1560       self->anc_width = 0;
1561       break;
1562     case GST_STATE_CHANGE_READY_TO_PAUSED:
1563       self->flushing = FALSE;
1564       break;
1565     default:
1566       break;
1567   }
1568
1569   if (ret == GST_STATE_CHANGE_FAILURE)
1570     return ret;
1571   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1572   if (ret == GST_STATE_CHANGE_FAILURE)
1573     return ret;
1574
1575   switch (transition) {
1576     case GST_STATE_CHANGE_PAUSED_TO_READY:
1577       self->signal_state = SIGNAL_STATE_UNKNOWN;
1578
1579       gst_decklink_video_src_stop (self);
1580       break;
1581     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
1582       HRESULT res;
1583
1584       GST_DEBUG_OBJECT (self, "Stopping streams");
1585
1586       res = self->input->input->StopStreams ();
1587       if (res != S_OK) {
1588         GST_ELEMENT_ERROR (self, STREAM, FAILED,
1589             (NULL), ("Failed to stop streams: 0x%08lx", (unsigned long) res));
1590         ret = GST_STATE_CHANGE_FAILURE;
1591       }
1592       break;
1593     }
1594     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
1595       g_mutex_lock (&self->input->lock);
1596       if (self->input->start_streams)
1597         self->input->start_streams (self->input->videosrc);
1598       g_mutex_unlock (&self->input->lock);
1599
1600       break;
1601     }
1602     case GST_STATE_CHANGE_READY_TO_NULL:
1603       gst_decklink_video_src_close (self);
1604       break;
1605     default:
1606       break;
1607   }
1608 out:
1609
1610   return ret;
1611 }