• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 2011 David Schleef <ds@entropywave.com>
3  * Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
18  * Boston, MA 02110-1335, USA.
19  */
20 /**
21  * SECTION:element-decklinkaudiosrc
22  * @short_description: Inputs Audio from a BlackMagic DeckLink Device
23  * @see_also: decklinkvideosrc
24  *
25  * Capture Video and Audio from a BlackMagic DeckLink Device. Can only be used
26  * in conjunction with decklinkvideosink.
27  *
28  * ## Sample pipeline
29  * |[
30  * gst-launch-1.0 \
31  *   decklinkvideosrc device-number=0 mode=1080p25 ! autovideosink \
32  *   decklinkaudiosrc device-number=0 ! autoaudiosink
33  * ]|
34  * Capturing 1080p25 video and audio from the SDI-In of Card 0. Devices are numbered
35  * starting with 0.
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 #include "gstdecklinkaudiosrc.h"
43 #include "gstdecklinkvideosrc.h"
44 #include <string.h>
45 
46 GST_DEBUG_CATEGORY_STATIC (gst_decklink_audio_src_debug);
47 #define GST_CAT_DEFAULT gst_decklink_audio_src_debug
48 
49 #define DEFAULT_CONNECTION            (GST_DECKLINK_AUDIO_CONNECTION_AUTO)
50 #define DEFAULT_BUFFER_SIZE           (5)
51 
52 #define DEFAULT_ALIGNMENT_THRESHOLD   (40 * GST_MSECOND)
53 #define DEFAULT_DISCONT_WAIT          (1 * GST_SECOND)
54 #define DEFAULT_CHANNELS              (GST_DECKLINK_AUDIO_CHANNELS_2)
55 
56 #ifndef ABSDIFF
57 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
58 #endif
59 
60 enum
61 {
62   PROP_0,
63   PROP_CONNECTION,
64   PROP_DEVICE_NUMBER,
65   PROP_ALIGNMENT_THRESHOLD,
66   PROP_DISCONT_WAIT,
67   PROP_BUFFER_SIZE,
68   PROP_CHANNELS,
69   PROP_HW_SERIAL_NUMBER
70 };
71 
72 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("src",
73     GST_PAD_SRC,
74     GST_PAD_ALWAYS,
75     GST_STATIC_CAPS
76     ("audio/x-raw, format={S16LE,S32LE}, channels=2, rate=48000, "
77         "layout=interleaved;"
78         "audio/x-raw, format={S16LE,S32LE}, channels={8,16}, channel-mask=(bitmask)0, rate=48000, "
79         "layout=interleaved")
80     );
81 
82 typedef struct
83 {
84   IDeckLinkAudioInputPacket *packet;
85   GstClockTime timestamp;
86   GstClockTime stream_timestamp;
87   GstClockTime stream_duration;
88   GstClockTime hardware_timestamp;
89   GstClockTime hardware_duration;
90   gboolean no_signal;
91 } CapturePacket;
92 
93 static void
capture_packet_clear(CapturePacket * packet)94 capture_packet_clear (CapturePacket * packet)
95 {
96   packet->packet->Release ();
97   memset (packet, 0, sizeof (*packet));
98 }
99 
100 typedef struct
101 {
102   IDeckLinkAudioInputPacket *packet;
103   IDeckLinkInput *input;
104 } AudioPacket;
105 
106 static void
audio_packet_free(void * data)107 audio_packet_free (void *data)
108 {
109   AudioPacket *packet = (AudioPacket *) data;
110 
111   packet->packet->Release ();
112   packet->input->Release ();
113   g_free (packet);
114 }
115 
116 static void gst_decklink_audio_src_set_property (GObject * object,
117     guint property_id, const GValue * value, GParamSpec * pspec);
118 static void gst_decklink_audio_src_get_property (GObject * object,
119     guint property_id, GValue * value, GParamSpec * pspec);
120 static void gst_decklink_audio_src_finalize (GObject * object);
121 
122 static GstStateChangeReturn
123 gst_decklink_audio_src_change_state (GstElement * element,
124     GstStateChange transition);
125 
126 static gboolean gst_decklink_audio_src_unlock (GstBaseSrc * bsrc);
127 static gboolean gst_decklink_audio_src_unlock_stop (GstBaseSrc * bsrc);
128 static GstCaps *gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc,
129     GstCaps * filter);
130 static gboolean gst_decklink_audio_src_query (GstBaseSrc * bsrc,
131     GstQuery * query);
132 
133 static GstFlowReturn gst_decklink_audio_src_create (GstPushSrc * psrc,
134     GstBuffer ** buffer);
135 
136 static gboolean gst_decklink_audio_src_open (GstDecklinkAudioSrc * self);
137 static gboolean gst_decklink_audio_src_close (GstDecklinkAudioSrc * self);
138 
139 static gboolean gst_decklink_audio_src_stop (GstDecklinkAudioSrc * self);
140 
141 #define parent_class gst_decklink_audio_src_parent_class
142 G_DEFINE_TYPE (GstDecklinkAudioSrc, gst_decklink_audio_src, GST_TYPE_PUSH_SRC);
143 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (decklinkaudiosrc, "decklinkaudiosrc", GST_RANK_NONE,
144     GST_TYPE_DECKLINK_AUDIO_SRC, decklink_element_init (plugin));
145 
146 static void
gst_decklink_audio_src_class_init(GstDecklinkAudioSrcClass * klass)147 gst_decklink_audio_src_class_init (GstDecklinkAudioSrcClass * klass)
148 {
149   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
150   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
151   GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
152   GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass);
153 
154   gobject_class->set_property = gst_decklink_audio_src_set_property;
155   gobject_class->get_property = gst_decklink_audio_src_get_property;
156   gobject_class->finalize = gst_decklink_audio_src_finalize;
157 
158   element_class->change_state =
159       GST_DEBUG_FUNCPTR (gst_decklink_audio_src_change_state);
160 
161   basesrc_class->query = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_query);
162   basesrc_class->negotiate = NULL;
163   basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_get_caps);
164   basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock);
165   basesrc_class->unlock_stop =
166       GST_DEBUG_FUNCPTR (gst_decklink_audio_src_unlock_stop);
167 
168   pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_decklink_audio_src_create);
169 
170   g_object_class_install_property (gobject_class, PROP_CONNECTION,
171       g_param_spec_enum ("connection", "Connection",
172           "Audio input connection to use",
173           GST_TYPE_DECKLINK_AUDIO_CONNECTION, DEFAULT_CONNECTION,
174           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
175               G_PARAM_CONSTRUCT)));
176 
177   g_object_class_install_property (gobject_class, PROP_DEVICE_NUMBER,
178       g_param_spec_int ("device-number", "Device number",
179           "Output device instance to use", 0, G_MAXINT, 0,
180           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
181               G_PARAM_CONSTRUCT)));
182 
183   g_object_class_install_property (gobject_class, PROP_ALIGNMENT_THRESHOLD,
184       g_param_spec_uint64 ("alignment-threshold", "Alignment Threshold",
185           "Timestamp alignment threshold in nanoseconds", 0,
186           G_MAXUINT64 - 1, DEFAULT_ALIGNMENT_THRESHOLD,
187           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
188 
189   g_object_class_install_property (gobject_class, PROP_DISCONT_WAIT,
190       g_param_spec_uint64 ("discont-wait", "Discont Wait",
191           "Window of time in nanoseconds to wait before "
192           "creating a discontinuity", 0,
193           G_MAXUINT64 - 1, DEFAULT_DISCONT_WAIT,
194           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
195 
196   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
197       g_param_spec_uint ("buffer-size", "Buffer Size",
198           "Size of internal buffer in number of video frames", 1,
199           G_MAXINT, DEFAULT_BUFFER_SIZE,
200           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
201 
202   g_object_class_install_property (gobject_class, PROP_CHANNELS,
203       g_param_spec_enum ("channels", "Channels",
204           "Audio channels",
205           GST_TYPE_DECKLINK_AUDIO_CHANNELS, DEFAULT_CHANNELS,
206           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
207               G_PARAM_CONSTRUCT)));
208 
209   g_object_class_install_property (gobject_class, PROP_HW_SERIAL_NUMBER,
210       g_param_spec_string ("hw-serial-number", "Hardware serial number",
211           "The serial number (hardware ID) of the Decklink card",
212           NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
213 
214   gst_element_class_add_static_pad_template (element_class, &sink_template);
215 
216   gst_element_class_set_static_metadata (element_class, "Decklink Audio Source",
217       "Audio/Source/Hardware", "Decklink Source",
218       "David Schleef <ds@entropywave.com>, "
219       "Sebastian Dröge <sebastian@centricular.com>");
220 
221   GST_DEBUG_CATEGORY_INIT (gst_decklink_audio_src_debug, "decklinkaudiosrc",
222       0, "debug category for decklinkaudiosrc element");
223 }
224 
225 static void
gst_decklink_audio_src_init(GstDecklinkAudioSrc * self)226 gst_decklink_audio_src_init (GstDecklinkAudioSrc * self)
227 {
228   self->device_number = 0;
229   self->alignment_threshold = DEFAULT_ALIGNMENT_THRESHOLD;
230   self->discont_wait = DEFAULT_DISCONT_WAIT;
231   self->buffer_size = DEFAULT_BUFFER_SIZE;
232   self->channels = DEFAULT_CHANNELS;
233 
234   gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
235   gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
236 
237   gst_pad_use_fixed_caps (GST_BASE_SRC_PAD (self));
238 
239   g_mutex_init (&self->lock);
240   g_cond_init (&self->cond);
241 
242   self->current_packets =
243       gst_queue_array_new_for_struct (sizeof (CapturePacket),
244       DEFAULT_BUFFER_SIZE);
245 
246   self->skipped_last = 0;
247   self->skip_from_timestamp = GST_CLOCK_TIME_NONE;
248   self->skip_to_timestamp = GST_CLOCK_TIME_NONE;
249 }
250 
251 void
gst_decklink_audio_src_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)252 gst_decklink_audio_src_set_property (GObject * object, guint property_id,
253     const GValue * value, GParamSpec * pspec)
254 {
255   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (object);
256 
257   switch (property_id) {
258     case PROP_CONNECTION:
259       self->connection =
260           (GstDecklinkAudioConnectionEnum) g_value_get_enum (value);
261       break;
262     case PROP_DEVICE_NUMBER:
263       self->device_number = g_value_get_int (value);
264       break;
265     case PROP_ALIGNMENT_THRESHOLD:
266       self->alignment_threshold = g_value_get_uint64 (value);
267       break;
268     case PROP_DISCONT_WAIT:
269       self->discont_wait = g_value_get_uint64 (value);
270       break;
271     case PROP_BUFFER_SIZE:
272       self->buffer_size = g_value_get_uint (value);
273       break;
274     case PROP_CHANNELS:
275       self->channels = (GstDecklinkAudioChannelsEnum) g_value_get_enum (value);
276       break;
277     default:
278       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
279       break;
280   }
281 }
282 
283 void
gst_decklink_audio_src_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)284 gst_decklink_audio_src_get_property (GObject * object, guint property_id,
285     GValue * value, GParamSpec * pspec)
286 {
287   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (object);
288 
289   switch (property_id) {
290     case PROP_CONNECTION:
291       g_value_set_enum (value, self->connection);
292       break;
293     case PROP_DEVICE_NUMBER:
294       g_value_set_int (value, self->device_number);
295       break;
296     case PROP_ALIGNMENT_THRESHOLD:
297       g_value_set_uint64 (value, self->alignment_threshold);
298       break;
299     case PROP_DISCONT_WAIT:
300       g_value_set_uint64 (value, self->discont_wait);
301       break;
302     case PROP_BUFFER_SIZE:
303       g_value_set_uint (value, self->buffer_size);
304       break;
305     case PROP_CHANNELS:
306       g_value_set_enum (value, self->channels);
307       break;
308     case PROP_HW_SERIAL_NUMBER:
309       if (self->input)
310         g_value_set_string (value, self->input->hw_serial_number);
311       else
312         g_value_set_string (value, NULL);
313       break;
314     default:
315       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
316       break;
317   }
318 }
319 
320 void
gst_decklink_audio_src_finalize(GObject * object)321 gst_decklink_audio_src_finalize (GObject * object)
322 {
323   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (object);
324 
325   g_mutex_clear (&self->lock);
326   g_cond_clear (&self->cond);
327   if (self->current_packets) {
328     while (gst_queue_array_get_length (self->current_packets) > 0) {
329       CapturePacket *tmp = (CapturePacket *)
330           gst_queue_array_pop_head_struct (self->current_packets);
331       capture_packet_clear (tmp);
332     }
333     gst_queue_array_free (self->current_packets);
334     self->current_packets = NULL;
335   }
336 
337   G_OBJECT_CLASS (parent_class)->finalize (object);
338 }
339 
340 static gboolean
gst_decklink_audio_src_start(GstDecklinkAudioSrc * self)341 gst_decklink_audio_src_start (GstDecklinkAudioSrc * self)
342 {
343   BMDAudioSampleType sample_depth;
344   HRESULT ret;
345   BMDAudioConnection conn = (BMDAudioConnection) - 1;
346   GstCaps *allowed_caps, *caps;
347 
348   g_mutex_lock (&self->input->lock);
349   if (self->input->audio_enabled) {
350     g_mutex_unlock (&self->input->lock);
351     return TRUE;
352   }
353   g_mutex_unlock (&self->input->lock);
354 
355   /* Negotiate the format / sample depth with downstream */
356   allowed_caps = gst_pad_get_allowed_caps (GST_BASE_SRC_PAD (self));
357   if (!allowed_caps)
358     allowed_caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (self));
359 
360   sample_depth = bmdAudioSampleType32bitInteger;
361   if (!gst_caps_is_empty (allowed_caps)) {
362     GstStructure *s;
363 
364     allowed_caps = gst_caps_simplify (allowed_caps);
365 
366     s = gst_caps_get_structure (allowed_caps, 0);
367 
368     /* If it's not a string then both formats are supported */
369     if (gst_structure_has_field_typed (s, "format", G_TYPE_STRING)) {
370       const gchar *format = gst_structure_get_string (s, "format");
371       if (g_str_equal (format, "S16LE")) {
372         sample_depth = bmdAudioSampleType16bitInteger;
373       }
374     }
375   }
376   gst_caps_unref (allowed_caps);
377 
378   switch (self->connection) {
379     case GST_DECKLINK_AUDIO_CONNECTION_AUTO:{
380       GstElement *videosrc = NULL;
381       GstDecklinkConnectionEnum vconn;
382 
383       // Try to get the connection from the videosrc and try
384       // to select a sensible audio connection based on that
385       g_mutex_lock (&self->input->lock);
386       if (self->input->videosrc)
387         videosrc = GST_ELEMENT_CAST (gst_object_ref (self->input->videosrc));
388       g_mutex_unlock (&self->input->lock);
389 
390       if (videosrc) {
391         g_object_get (videosrc, "connection", &vconn, NULL);
392         gst_object_unref (videosrc);
393 
394         switch (vconn) {
395           case GST_DECKLINK_CONNECTION_SDI:
396             conn = bmdAudioConnectionEmbedded;
397             break;
398           case GST_DECKLINK_CONNECTION_HDMI:
399             conn = bmdAudioConnectionEmbedded;
400             break;
401           case GST_DECKLINK_CONNECTION_OPTICAL_SDI:
402             conn = bmdAudioConnectionEmbedded;
403             break;
404           case GST_DECKLINK_CONNECTION_COMPONENT:
405             conn = bmdAudioConnectionAnalog;
406             break;
407           case GST_DECKLINK_CONNECTION_COMPOSITE:
408             conn = bmdAudioConnectionAnalog;
409             break;
410           case GST_DECKLINK_CONNECTION_SVIDEO:
411             conn = bmdAudioConnectionAnalog;
412             break;
413           default:
414             // Use default
415             break;
416         }
417       }
418 
419       break;
420     }
421     case GST_DECKLINK_AUDIO_CONNECTION_EMBEDDED:
422       conn = bmdAudioConnectionEmbedded;
423       break;
424     case GST_DECKLINK_AUDIO_CONNECTION_AES_EBU:
425       conn = bmdAudioConnectionAESEBU;
426       break;
427     case GST_DECKLINK_AUDIO_CONNECTION_ANALOG:
428       conn = bmdAudioConnectionAnalog;
429       break;
430     case GST_DECKLINK_AUDIO_CONNECTION_ANALOG_XLR:
431       conn = bmdAudioConnectionAnalogXLR;
432       break;
433     case GST_DECKLINK_AUDIO_CONNECTION_ANALOG_RCA:
434       conn = bmdAudioConnectionAnalogRCA;
435       break;
436     default:
437       g_assert_not_reached ();
438       break;
439   }
440 
441   if (conn != (BMDAudioConnection) - 1) {
442     ret =
443         self->input->config->SetInt (bmdDeckLinkConfigAudioInputConnection,
444         conn);
445     if (ret != S_OK) {
446       GST_ERROR ("set configuration (audio input connection): 0x%08lx",
447           (unsigned long) ret);
448       return FALSE;
449     }
450   }
451 
452   ret = self->input->input->EnableAudioInput (bmdAudioSampleRate48kHz,
453       sample_depth, self->channels_found);
454   if (ret != S_OK) {
455     GST_WARNING_OBJECT (self, "Failed to enable audio input: 0x%08lx",
456         (unsigned long) ret);
457     return FALSE;
458   }
459   gst_audio_info_set_format (&self->info,
460       sample_depth ==
461       bmdAudioSampleType16bitInteger ? GST_AUDIO_FORMAT_S16LE :
462       GST_AUDIO_FORMAT_S32LE, 48000, self->channels_found, NULL);
463 
464   g_mutex_lock (&self->input->lock);
465   self->input->audio_enabled = TRUE;
466   if (self->input->start_streams && self->input->videosrc)
467     self->input->start_streams (self->input->videosrc);
468   g_mutex_unlock (&self->input->lock);
469 
470   caps = gst_audio_info_to_caps (&self->info);
471   if (!gst_base_src_set_caps (GST_BASE_SRC (self), caps)) {
472     gst_caps_unref (caps);
473     GST_WARNING_OBJECT (self, "Failed to set caps");
474     return FALSE;
475   }
476   gst_caps_unref (caps);
477 
478   self->skipped_last = 0;
479   self->skip_from_timestamp = GST_CLOCK_TIME_NONE;
480   self->skip_to_timestamp = GST_CLOCK_TIME_NONE;
481 
482   return TRUE;
483 }
484 
485 static void
gst_decklink_audio_src_got_packet(GstElement * element,IDeckLinkAudioInputPacket * packet,GstClockTime capture_time,GstClockTime stream_time,GstClockTime stream_duration,GstClockTime hardware_time,GstClockTime hardware_duration,gboolean no_signal)486 gst_decklink_audio_src_got_packet (GstElement * element,
487     IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
488     GstClockTime stream_time, GstClockTime stream_duration,
489     GstClockTime hardware_time, GstClockTime hardware_duration,
490     gboolean no_signal)
491 {
492   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (element);
493   GstClockTime timestamp = GST_CLOCK_TIME_NONE;
494 
495   GST_LOG_OBJECT (self,
496       "Got audio packet at %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT
497       ", no signal %d", GST_TIME_ARGS (capture_time),
498       GST_TIME_ARGS (stream_time), no_signal);
499 
500   g_mutex_lock (&self->input->lock);
501   if (self->input->videosrc) {
502     GstDecklinkVideoSrc *videosrc =
503         GST_DECKLINK_VIDEO_SRC_CAST (gst_object_ref (self->input->videosrc));
504 
505     if (videosrc->drop_no_signal_frames && no_signal) {
506       g_mutex_unlock (&self->input->lock);
507       return;
508     }
509 
510     if (videosrc->first_time == GST_CLOCK_TIME_NONE)
511       videosrc->first_time = stream_time;
512 
513     if (GST_CLOCK_TIME_IS_VALID (videosrc->first_time) &&
514         GST_CLOCK_TIME_IS_VALID (stream_time) &&
515         videosrc->skip_first_time > 0 &&
516         stream_time - videosrc->first_time < videosrc->skip_first_time) {
517       GST_DEBUG_OBJECT (self,
518           "Skipping frame as requested: %" GST_TIME_FORMAT " < %"
519           GST_TIME_FORMAT, GST_TIME_ARGS (stream_time),
520           GST_TIME_ARGS (videosrc->skip_first_time + videosrc->first_time));
521       g_mutex_unlock (&self->input->lock);
522       return;
523     }
524 
525     if (videosrc->output_stream_time)
526       timestamp = stream_time;
527     else if (GST_CLOCK_TIME_IS_VALID (stream_time))
528       timestamp = gst_clock_adjust_with_calibration (NULL, stream_time,
529           videosrc->current_time_mapping.xbase,
530           videosrc->current_time_mapping.b, videosrc->current_time_mapping.num,
531           videosrc->current_time_mapping.den);
532   } else {
533     timestamp = capture_time;
534   }
535   g_mutex_unlock (&self->input->lock);
536 
537   GST_LOG_OBJECT (self, "Converted times to %" GST_TIME_FORMAT,
538       GST_TIME_ARGS (timestamp));
539 
540   g_mutex_lock (&self->lock);
541   if (!self->flushing) {
542     CapturePacket p;
543     guint skipped_packets = 0;
544 
545     while (gst_queue_array_get_length (self->current_packets) >=
546         self->buffer_size) {
547       CapturePacket *tmp = (CapturePacket *)
548           gst_queue_array_pop_head_struct (self->current_packets);
549       if (skipped_packets == 0 && self->skipped_last == 0)
550         self->skip_from_timestamp = tmp->timestamp;
551       skipped_packets++;
552       self->skip_to_timestamp = tmp->timestamp;
553       capture_packet_clear (tmp);
554     }
555 
556     if (self->skipped_last == 0 && skipped_packets > 0) {
557       GST_WARNING_OBJECT (self, "Starting to drop audio packets");
558     }
559 
560     if (skipped_packets == 0 && self->skipped_last > 0) {
561       GST_ELEMENT_WARNING_WITH_DETAILS (self,
562           STREAM, FAILED,
563           ("Dropped %u old packets from %" GST_TIME_FORMAT " to %"
564               GST_TIME_FORMAT, self->skipped_last,
565               GST_TIME_ARGS (self->skip_from_timestamp),
566               GST_TIME_ARGS (self->skip_to_timestamp)),
567           (NULL),
568           ("dropped", G_TYPE_UINT, self->skipped_last,
569               "from", G_TYPE_UINT64, self->skip_from_timestamp,
570               "to", G_TYPE_UINT64, self->skip_to_timestamp, NULL));
571       self->skipped_last = 0;
572     }
573     self->skipped_last += skipped_packets;
574 
575     memset (&p, 0, sizeof (p));
576     p.packet = packet;
577     p.timestamp = timestamp;
578     p.stream_timestamp = stream_time;
579     p.stream_duration = stream_duration;
580     p.hardware_timestamp = hardware_time;
581     p.hardware_duration = hardware_duration;
582     p.no_signal = no_signal;
583     packet->AddRef ();
584     gst_queue_array_push_tail_struct (self->current_packets, &p);
585     g_cond_signal (&self->cond);
586   }
587   g_mutex_unlock (&self->lock);
588 }
589 
590 static GstFlowReturn
gst_decklink_audio_src_create(GstPushSrc * bsrc,GstBuffer ** buffer)591 gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
592 {
593   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
594   GstFlowReturn flow_ret = GST_FLOW_OK;
595   const guint8 *data;
596   glong sample_count;
597   gsize data_size;
598   CapturePacket p;
599   AudioPacket *ap;
600   GstClockTime timestamp, duration;
601   GstClockTime start_time, end_time;
602   guint64 start_offset, end_offset;
603   gboolean discont = FALSE;
604   static GstStaticCaps stream_reference =
605       GST_STATIC_CAPS ("timestamp/x-decklink-stream");
606   static GstStaticCaps hardware_reference =
607       GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
608 
609   if (!gst_decklink_audio_src_start (self)) {
610     return GST_FLOW_NOT_NEGOTIATED;
611   }
612 
613 retry:
614   g_mutex_lock (&self->lock);
615   while (gst_queue_array_is_empty (self->current_packets) && !self->flushing) {
616     g_cond_wait (&self->cond, &self->lock);
617   }
618 
619   if (self->flushing) {
620     GST_DEBUG_OBJECT (self, "Flushing");
621     g_mutex_unlock (&self->lock);
622     return GST_FLOW_FLUSHING;
623   }
624 
625   p = *(CapturePacket *)
626       gst_queue_array_pop_head_struct (self->current_packets);
627   g_mutex_unlock (&self->lock);
628 
629   p.packet->GetBytes ((gpointer *) & data);
630   sample_count = p.packet->GetSampleFrameCount ();
631   data_size = self->info.bpf * sample_count;
632 
633   timestamp = p.timestamp;
634 
635   if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
636     if (self->next_offset == (guint64) - 1) {
637       GST_DEBUG_OBJECT (self,
638           "Got packet without timestamp before initial "
639           "timestamp after discont - dropping");
640       capture_packet_clear (&p);
641       goto retry;
642     } else {
643       GST_INFO_OBJECT (self, "Unknown timestamp value");
644 
645       /* Likely the case where IDeckLinkInputCallback::VideoInputFrameArrived()
646        * didn't provide video frame, so no reference video stream timestamp
647        * is available. It can happen as per SDK documentation
648        * under the following circumstances:
649        * - On Intensity Pro with progressive NTSC only, every video frame will
650        *   have two audio packets.
651        * - With 3:2 pulldown there are five audio packets for each four
652        *   video frames.
653        * - If video processing is not fast enough, audio will still be delivered
654        *
655        * Assume there was no packet drop from previous valid packet, and use
656        * previously calculated expected timestamp here */
657       timestamp = gst_util_uint64_scale (self->next_offset,
658           GST_SECOND, self->info.rate);
659     }
660   }
661 
662   ap = (AudioPacket *) g_malloc0 (sizeof (AudioPacket));
663 
664   *buffer =
665       gst_buffer_new_wrapped_full ((GstMemoryFlags) GST_MEMORY_FLAG_READONLY,
666       (gpointer) data, data_size, 0, data_size, ap,
667       (GDestroyNotify) audio_packet_free);
668 
669   ap->packet = p.packet;
670   p.packet->AddRef ();
671   ap->input = self->input->input;
672   ap->input->AddRef ();
673 
674   // Jitter and discontinuity handling, based on audiobasesrc
675   start_time = timestamp;
676 
677   // Convert to the sample numbers
678   start_offset =
679       gst_util_uint64_scale (start_time, self->info.rate, GST_SECOND);
680   // Convert back to round down to a sample multiple and get rid of rounding errors
681   start_time = gst_util_uint64_scale (start_offset, GST_SECOND, self->info.rate);
682 
683   end_offset = start_offset + sample_count;
684   end_time = gst_util_uint64_scale_int (end_offset, GST_SECOND,
685       self->info.rate);
686 
687   duration = end_time - start_time;
688 
689   if (self->next_offset == (guint64) - 1) {
690     discont = TRUE;
691   } else {
692     guint64 diff, max_sample_diff;
693 
694     // Check discont
695     if (start_offset <= self->next_offset)
696       diff = self->next_offset - start_offset;
697     else
698       diff = start_offset - self->next_offset;
699 
700     max_sample_diff =
701         gst_util_uint64_scale_int (self->alignment_threshold, self->info.rate,
702         GST_SECOND);
703 
704     // Discont!
705     if (self->alignment_threshold > 0
706         && self->alignment_threshold != GST_CLOCK_TIME_NONE
707         && G_UNLIKELY (diff >= max_sample_diff)) {
708       if (self->discont_wait > 0) {
709         if (self->discont_time == GST_CLOCK_TIME_NONE) {
710           self->discont_time = start_time;
711         } else if (start_time - self->discont_time >= self->discont_wait) {
712           discont = TRUE;
713           self->discont_time = GST_CLOCK_TIME_NONE;
714         }
715       } else {
716         discont = TRUE;
717       }
718     } else if (G_UNLIKELY (self->discont_time != GST_CLOCK_TIME_NONE)) {
719       // we have had a discont, but are now back on track!
720       self->discont_time = GST_CLOCK_TIME_NONE;
721     }
722   }
723 
724   if (discont) {
725     // Have discont, need resync and use the capture timestamps
726     if (self->next_offset != (guint64) - 1)
727       GST_INFO_OBJECT (self, "Have discont. Expected %"
728           G_GUINT64_FORMAT ", got %" G_GUINT64_FORMAT,
729           self->next_offset, start_offset);
730     GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_DISCONT);
731     self->next_offset = end_offset;
732     // Got a discont and adjusted, reset the discont_time marker.
733     self->discont_time = GST_CLOCK_TIME_NONE;
734   } else if (self->alignment_threshold == 0) {
735     // Don't align, just pass through timestamps
736   } else {
737     // No discont, just keep counting
738     timestamp =
739         gst_util_uint64_scale (self->next_offset, GST_SECOND, self->info.rate);
740     self->next_offset += sample_count;
741     duration =
742         gst_util_uint64_scale (self->next_offset, GST_SECOND,
743         self->info.rate) - timestamp;
744   }
745 
746   // Detect gaps in stream time
747   self->processed += sample_count;
748   if (self->expected_stream_time != GST_CLOCK_TIME_NONE
749       && p.stream_timestamp == GST_CLOCK_TIME_NONE) {
750     /* We missed a frame. Extrapolate the timestamps */
751     p.stream_timestamp = self->expected_stream_time;
752     p.stream_duration =
753         gst_util_uint64_scale_int (sample_count, GST_SECOND, self->info.rate);
754   }
755   if (self->last_hardware_time != GST_CLOCK_TIME_NONE
756       && p.hardware_timestamp == GST_CLOCK_TIME_NONE) {
757     /* This should always happen when the previous one also does, but let's
758      * have two separate checks just in case */
759     GstClockTime start_hw_offset, end_hw_offset;
760     start_hw_offset =
761         gst_util_uint64_scale (self->last_hardware_time, self->info.rate,
762         GST_SECOND);
763     end_hw_offset = start_hw_offset + sample_count;
764     p.hardware_timestamp =
765         gst_util_uint64_scale_int (end_hw_offset, GST_SECOND, self->info.rate);
766     /* Will be the same as the stream duration - reuse it */
767     p.hardware_duration = p.stream_duration;
768   }
769 
770   if (p.stream_timestamp != GST_CLOCK_TIME_NONE) {
771     GstClockTime start_stream_time, end_stream_time;
772 
773     start_stream_time = p.stream_timestamp;
774 
775     start_offset =
776         gst_util_uint64_scale (start_stream_time, self->info.rate, GST_SECOND);
777 
778     end_offset = start_offset + sample_count;
779     end_stream_time = gst_util_uint64_scale_int (end_offset, GST_SECOND,
780         self->info.rate);
781 
782     /* With drop-frame we have gaps of 1 sample every now and then (rounding
783      * errors because of the samples-per-frame pattern which is not 100%
784      * accurate), and due to rounding errors in the calculations these can be
785      * 2>x>1 */
786     if (self->expected_stream_time != GST_CLOCK_TIME_NONE &&
787         ABSDIFF (self->expected_stream_time, p.stream_timestamp) >
788         gst_util_uint64_scale (2, GST_SECOND, self->info.rate)) {
789       GstMessage *msg;
790       GstClockTime running_time;
791 
792       self->dropped +=
793           gst_util_uint64_scale (ABSDIFF (self->expected_stream_time,
794               p.stream_timestamp), self->info.rate, GST_SECOND);
795       running_time =
796           gst_segment_to_running_time (&GST_BASE_SRC (self)->segment,
797           GST_FORMAT_TIME, timestamp);
798 
799       msg =
800           gst_message_new_qos (GST_OBJECT (self), TRUE, running_time,
801           p.stream_timestamp, timestamp, duration);
802       gst_message_set_qos_stats (msg, GST_FORMAT_DEFAULT, self->processed,
803           self->dropped);
804       gst_element_post_message (GST_ELEMENT (self), msg);
805     }
806     self->expected_stream_time = end_stream_time;
807   }
808   self->last_hardware_time = p.hardware_timestamp;
809 
810   if (p.no_signal)
811     GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_GAP);
812   GST_BUFFER_TIMESTAMP (*buffer) = timestamp;
813   GST_BUFFER_DURATION (*buffer) = duration;
814 
815   gst_buffer_add_reference_timestamp_meta (*buffer,
816       gst_static_caps_get (&stream_reference), p.stream_timestamp,
817       p.stream_duration);
818   gst_buffer_add_reference_timestamp_meta (*buffer,
819       gst_static_caps_get (&hardware_reference), p.hardware_timestamp,
820       p.hardware_duration);
821 
822   GST_DEBUG_OBJECT (self,
823       "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
824       GST_TIME_FORMAT, *buffer, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*buffer)),
825       GST_TIME_ARGS (GST_BUFFER_DURATION (*buffer)));
826 
827   capture_packet_clear (&p);
828 
829   return flow_ret;
830 }
831 
832 static GstCaps *
gst_decklink_audio_src_get_caps(GstBaseSrc * bsrc,GstCaps * filter)833 gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
834 {
835   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
836   GstCaps *caps, *template_caps;
837   const GstStructure *s;
838   gint channels;
839 
840   channels = self->channels;
841   if (channels == 0)
842     channels = self->channels_found;
843 
844   template_caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc));
845   if (channels == 0) {
846     caps = template_caps;
847   } else {
848     if (channels > 2)
849       s = gst_caps_get_structure (template_caps, 1);
850     else
851       s = gst_caps_get_structure (template_caps, 0);
852 
853     caps = gst_caps_new_full (gst_structure_copy (s), NULL);
854     gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels, NULL);
855     gst_caps_unref (template_caps);
856   }
857 
858   if (filter) {
859     GstCaps *tmp =
860         gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
861     gst_caps_unref (caps);
862     caps = tmp;
863   }
864 
865   return caps;
866 }
867 
868 static gboolean
gst_decklink_audio_src_query(GstBaseSrc * bsrc,GstQuery * query)869 gst_decklink_audio_src_query (GstBaseSrc * bsrc, GstQuery * query)
870 {
871   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
872   gboolean ret = TRUE;
873 
874   switch (GST_QUERY_TYPE (query)) {
875     case GST_QUERY_LATENCY:{
876       if (self->input) {
877         g_mutex_lock (&self->input->lock);
878         if (self->input->mode) {
879           GstClockTime min, max;
880 
881           min =
882               gst_util_uint64_scale_ceil (GST_SECOND, self->input->mode->fps_d,
883               self->input->mode->fps_n);
884           max = self->buffer_size * min;
885 
886           gst_query_set_latency (query, TRUE, min, max);
887           ret = TRUE;
888         } else {
889           ret = FALSE;
890         }
891         g_mutex_unlock (&self->input->lock);
892       } else {
893         ret = FALSE;
894       }
895 
896       break;
897     }
898     default:
899       ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
900       break;
901   }
902 
903   return ret;
904 }
905 
906 static gboolean
gst_decklink_audio_src_unlock(GstBaseSrc * bsrc)907 gst_decklink_audio_src_unlock (GstBaseSrc * bsrc)
908 {
909   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
910 
911   g_mutex_lock (&self->lock);
912   self->flushing = TRUE;
913   g_cond_signal (&self->cond);
914   g_mutex_unlock (&self->lock);
915 
916   return TRUE;
917 }
918 
919 static gboolean
gst_decklink_audio_src_unlock_stop(GstBaseSrc * bsrc)920 gst_decklink_audio_src_unlock_stop (GstBaseSrc * bsrc)
921 {
922   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (bsrc);
923 
924   g_mutex_lock (&self->lock);
925   self->flushing = FALSE;
926   while (gst_queue_array_get_length (self->current_packets) > 0) {
927     CapturePacket *tmp = (CapturePacket *)
928         gst_queue_array_pop_head_struct (self->current_packets);
929     capture_packet_clear (tmp);
930   }
931   g_mutex_unlock (&self->lock);
932 
933   return TRUE;
934 }
935 
936 static gboolean
gst_decklink_audio_src_open(GstDecklinkAudioSrc * self)937 gst_decklink_audio_src_open (GstDecklinkAudioSrc * self)
938 {
939   GST_DEBUG_OBJECT (self, "Opening");
940 
941   self->input =
942       gst_decklink_acquire_nth_input (self->device_number,
943       GST_ELEMENT_CAST (self), TRUE);
944   if (!self->input) {
945     GST_ERROR_OBJECT (self, "Failed to acquire input");
946     return FALSE;
947   }
948 
949   g_object_notify (G_OBJECT (self), "hw-serial-number");
950 
951   g_mutex_lock (&self->input->lock);
952   if (self->channels > 0) {
953     self->channels_found = self->channels;
954   } else {
955     if (self->input->attributes) {
956       int64_t channels_found;
957 
958       HRESULT ret = self->input->attributes->GetInt
959           (BMDDeckLinkMaximumAudioChannels, &channels_found);
960       self->channels_found = channels_found;
961 
962       /* Sometimes the card may report an invalid number of channels. In
963        * that case, we should (empirically) use 8. */
964       if (ret != S_OK ||
965           self->channels_found == 0 || g_enum_get_value ((GEnumClass *)
966               g_type_class_peek (GST_TYPE_DECKLINK_AUDIO_CHANNELS),
967               self->channels_found)
968           == NULL) {
969         self->channels_found = GST_DECKLINK_AUDIO_CHANNELS_8;
970       }
971     }
972   }
973   self->input->got_audio_packet = gst_decklink_audio_src_got_packet;
974   g_mutex_unlock (&self->input->lock);
975 
976   return TRUE;
977 }
978 
979 static gboolean
gst_decklink_audio_src_close(GstDecklinkAudioSrc * self)980 gst_decklink_audio_src_close (GstDecklinkAudioSrc * self)
981 {
982   GST_DEBUG_OBJECT (self, "Closing");
983 
984   if (self->input) {
985     g_mutex_lock (&self->input->lock);
986     self->input->got_audio_packet = NULL;
987     g_mutex_unlock (&self->input->lock);
988 
989     gst_decklink_release_nth_input (self->device_number,
990         GST_ELEMENT_CAST (self), TRUE);
991     self->input = NULL;
992   }
993 
994   return TRUE;
995 }
996 
997 static gboolean
gst_decklink_audio_src_stop(GstDecklinkAudioSrc * self)998 gst_decklink_audio_src_stop (GstDecklinkAudioSrc * self)
999 {
1000   GST_DEBUG_OBJECT (self, "Stopping");
1001 
1002   while (gst_queue_array_get_length (self->current_packets) > 0) {
1003     CapturePacket *tmp = (CapturePacket *)
1004         gst_queue_array_pop_head_struct (self->current_packets);
1005     capture_packet_clear (tmp);
1006   }
1007 
1008   if (self->input && self->input->audio_enabled) {
1009     g_mutex_lock (&self->input->lock);
1010     self->input->audio_enabled = FALSE;
1011     g_mutex_unlock (&self->input->lock);
1012 
1013     self->input->input->DisableAudioInput ();
1014   }
1015 
1016   return TRUE;
1017 }
1018 
1019 #if 0
1020 static gboolean
1021 in_same_pipeline (GstElement * a, GstElement * b)
1022 {
1023   GstObject *root = NULL, *tmp;
1024   gboolean ret = FALSE;
1025 
1026   tmp = gst_object_get_parent (GST_OBJECT_CAST (a));
1027   while (tmp != NULL) {
1028     if (root)
1029       gst_object_unref (root);
1030     root = tmp;
1031     tmp = gst_object_get_parent (root);
1032   }
1033 
1034   ret = root && gst_object_has_ancestor (GST_OBJECT_CAST (b), root);
1035 
1036   if (root)
1037     gst_object_unref (root);
1038 
1039   return ret;
1040 }
1041 #endif
1042 
1043 static GstStateChangeReturn
gst_decklink_audio_src_change_state(GstElement * element,GstStateChange transition)1044 gst_decklink_audio_src_change_state (GstElement * element,
1045     GstStateChange transition)
1046 {
1047   GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (element);
1048   GstStateChangeReturn ret;
1049 
1050   switch (transition) {
1051     case GST_STATE_CHANGE_NULL_TO_READY:
1052       self->processed = 0;
1053       self->dropped = 0;
1054       self->expected_stream_time = GST_CLOCK_TIME_NONE;
1055       if (!gst_decklink_audio_src_open (self)) {
1056         ret = GST_STATE_CHANGE_FAILURE;
1057         goto out;
1058       }
1059       break;
1060     case GST_STATE_CHANGE_READY_TO_PAUSED:{
1061       GstElement *videosrc = NULL;
1062 
1063       // Check if there is a video src for this input too and if it
1064       // is actually in the same pipeline
1065       g_mutex_lock (&self->input->lock);
1066       if (self->input->videosrc)
1067         videosrc = GST_ELEMENT_CAST (gst_object_ref (self->input->videosrc));
1068       g_mutex_unlock (&self->input->lock);
1069 
1070       if (!videosrc) {
1071         GST_ELEMENT_ERROR (self, STREAM, FAILED,
1072             (NULL), ("Audio src needs a video src for its operation"));
1073         ret = GST_STATE_CHANGE_FAILURE;
1074         goto out;
1075       }
1076       // FIXME: This causes deadlocks sometimes
1077 #if 0
1078       else if (!in_same_pipeline (GST_ELEMENT_CAST (self), videosrc)) {
1079         GST_ELEMENT_ERROR (self, STREAM, FAILED,
1080             (NULL),
1081             ("Audio src and video src need to be in the same pipeline"));
1082         ret = GST_STATE_CHANGE_FAILURE;
1083         gst_object_unref (videosrc);
1084         goto out;
1085       }
1086 #endif
1087 
1088       if (videosrc)
1089         gst_object_unref (videosrc);
1090 
1091       self->flushing = FALSE;
1092       self->next_offset = -1;
1093       break;
1094     }
1095     default:
1096       break;
1097   }
1098 
1099   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1100   if (ret == GST_STATE_CHANGE_FAILURE)
1101     return ret;
1102 
1103   switch (transition) {
1104     case GST_STATE_CHANGE_PAUSED_TO_READY:
1105       gst_decklink_audio_src_stop (self);
1106       break;
1107     case GST_STATE_CHANGE_READY_TO_NULL:
1108       gst_decklink_audio_src_close (self);
1109       break;
1110     default:
1111       break;
1112   }
1113 out:
1114 
1115   return ret;
1116 }
1117