1e44a3c38db11a973a51eafc93c28f39b84a870c
[platform/upstream/gstreamer.git] / sys / decklink / gstdecklinksrc.cpp
1 /* GStreamer
2  * Copyright (C) 2011 David Schleef <ds@schleef.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17  * Boston, MA 02110-1335, USA.
18  */
19 /**
20  * SECTION:element-gstdecklinksrc
21  *
22  * The decklinksrc element is a source element for Blackmagic
23  * Decklink cards.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
28  * gst-launch -v decklinksrc ! xvimagesink
29  * ]|
30  * 
31  * </refsect2>
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <gst/gst.h>
39 #include "gstdecklink.h"
40 #include "gstdecklinksrc.h"
41 #include "capture.h"
42 #include <string.h>
43
44 GST_DEBUG_CATEGORY (gst_decklink_src_debug_category);
45 #define GST_CAT_DEFAULT gst_decklink_src_debug_category
46
47 /* prototypes */
48
49
50 static void gst_decklink_src_set_property (GObject * object,
51     guint property_id, const GValue * value, GParamSpec * pspec);
52 static void gst_decklink_src_get_property (GObject * object,
53     guint property_id, GValue * value, GParamSpec * pspec);
54 static void gst_decklink_src_dispose (GObject * object);
55 static void gst_decklink_src_finalize (GObject * object);
56
57 static GstPad *gst_decklink_src_request_new_pad (GstElement * element,
58     GstPadTemplate * templ, const gchar * name);
59 static void gst_decklink_src_release_pad (GstElement * element, GstPad * pad);
60 static GstStateChangeReturn
61 gst_decklink_src_change_state (GstElement * element, GstStateChange transition);
62 static GstClock *gst_decklink_src_provide_clock (GstElement * element);
63 static gboolean gst_decklink_src_set_clock (GstElement * element,
64     GstClock * clock);
65 static GstIndex *gst_decklink_src_get_index (GstElement * element);
66 static void gst_decklink_src_set_index (GstElement * element, GstIndex * index);
67 static gboolean gst_decklink_src_send_event (GstElement * element,
68     GstEvent * event);
69 static gboolean gst_decklink_src_query (GstElement * element, GstQuery * query);
70
71 static GstCaps *gst_decklink_src_audio_src_getcaps (GstPad * pad);
72 static gboolean gst_decklink_src_audio_src_setcaps (GstPad * pad,
73     GstCaps * caps);
74 static gboolean gst_decklink_src_audio_src_acceptcaps (GstPad * pad,
75     GstCaps * caps);
76 static void gst_decklink_src_audio_src_fixatecaps (GstPad * pad,
77     GstCaps * caps);
78 static gboolean gst_decklink_src_audio_src_activate (GstPad * pad);
79 static gboolean gst_decklink_src_audio_src_activatepush (GstPad * pad,
80     gboolean active);
81 static gboolean gst_decklink_src_audio_src_activatepull (GstPad * pad,
82     gboolean active);
83 static GstPadLinkReturn gst_decklink_src_audio_src_link (GstPad * pad,
84     GstPad * peer);
85 static GstFlowReturn gst_decklink_src_audio_src_getrange (GstPad * pad,
86     guint64 offset, guint length, GstBuffer ** buffer);
87 static gboolean gst_decklink_src_audio_src_event (GstPad * pad,
88     GstEvent * event);
89 static gboolean gst_decklink_src_audio_src_query (GstPad * pad,
90     GstQuery * query);
91 static GstIterator *gst_decklink_src_audio_src_iterintlink (GstPad * pad);
92
93
94 static GstCaps *gst_decklink_src_video_src_getcaps (GstPad * pad);
95 static gboolean gst_decklink_src_video_src_setcaps (GstPad * pad,
96     GstCaps * caps);
97 static gboolean gst_decklink_src_video_src_acceptcaps (GstPad * pad,
98     GstCaps * caps);
99 static void gst_decklink_src_video_src_fixatecaps (GstPad * pad,
100     GstCaps * caps);
101 static gboolean gst_decklink_src_video_src_activate (GstPad * pad);
102 static gboolean gst_decklink_src_video_src_activatepush (GstPad * pad,
103     gboolean active);
104 static gboolean gst_decklink_src_video_src_activatepull (GstPad * pad,
105     gboolean active);
106 static GstPadLinkReturn gst_decklink_src_video_src_link (GstPad * pad,
107     GstPad * peer);
108 static GstFlowReturn gst_decklink_src_video_src_getrange (GstPad * pad,
109     guint64 offset, guint length, GstBuffer ** buffer);
110 static gboolean gst_decklink_src_video_src_event (GstPad * pad,
111     GstEvent * event);
112 static gboolean gst_decklink_src_video_src_query (GstPad * pad,
113     GstQuery * query);
114 static GstIterator *gst_decklink_src_video_src_iterintlink (GstPad * pad);
115
116 static void gst_decklink_src_task (void *priv);
117
118 #ifdef _MSC_VER
119 /* COM initialization/uninitialization thread */
120 static void gst_decklink_src_com_thread (GstDecklinkSrc * src);
121 #endif /* _MSC_VER */
122
123 enum
124 {
125   PROP_0,
126   PROP_MODE,
127   PROP_CONNECTION,
128   PROP_AUDIO_INPUT,
129   PROP_SUBDEVICE
130 };
131
132 /* pad templates */
133
134 static GstStaticPadTemplate gst_decklink_src_audio_src_template =
135 GST_STATIC_PAD_TEMPLATE ("audiosrc",
136     GST_PAD_SRC,
137     GST_PAD_ALWAYS,
138     GST_STATIC_CAPS ("audio/x-raw-int,width=16,depth=16,channels=2,rate=48000")
139     );
140
141 /* the video source pad template is created on the fly */
142
143 /* class initialization */
144
145 #define DEBUG_INIT(bla) \
146   GST_DEBUG_CATEGORY_INIT (gst_decklink_src_debug_category, "decklinksrc", 0, \
147       "debug category for decklinksrc element");
148
149 GST_BOILERPLATE_FULL (GstDecklinkSrc, gst_decklink_src, GstElement,
150     GST_TYPE_ELEMENT, DEBUG_INIT);
151
152 static void
153 gst_decklink_src_base_init (gpointer g_class)
154 {
155   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
156
157   gst_element_class_add_pad_template (element_class,
158       gst_static_pad_template_get (&gst_decklink_src_audio_src_template));
159   gst_element_class_add_pad_template (element_class,
160       gst_pad_template_new ("videosrc", GST_PAD_SRC, GST_PAD_ALWAYS,
161           gst_decklink_mode_get_template_caps ()));
162
163   gst_element_class_set_details_simple (element_class, "Decklink source",
164       "Source/Video", "DeckLink Source", "David Schleef <ds@entropywave.com>");
165 }
166
167 static void
168 gst_decklink_src_class_init (GstDecklinkSrcClass * klass)
169 {
170   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
171   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
172
173   gobject_class->set_property = gst_decklink_src_set_property;
174   gobject_class->get_property = gst_decklink_src_get_property;
175   gobject_class->dispose = gst_decklink_src_dispose;
176   gobject_class->finalize = gst_decklink_src_finalize;
177   element_class->request_new_pad =
178       GST_DEBUG_FUNCPTR (gst_decklink_src_request_new_pad);
179   element_class->release_pad = GST_DEBUG_FUNCPTR (gst_decklink_src_release_pad);
180   element_class->change_state =
181       GST_DEBUG_FUNCPTR (gst_decklink_src_change_state);
182   element_class->provide_clock =
183       GST_DEBUG_FUNCPTR (gst_decklink_src_provide_clock);
184   element_class->set_clock = GST_DEBUG_FUNCPTR (gst_decklink_src_set_clock);
185   element_class->get_index = GST_DEBUG_FUNCPTR (gst_decklink_src_get_index);
186   element_class->set_index = GST_DEBUG_FUNCPTR (gst_decklink_src_set_index);
187   element_class->send_event = GST_DEBUG_FUNCPTR (gst_decklink_src_send_event);
188   element_class->query = GST_DEBUG_FUNCPTR (gst_decklink_src_query);
189
190   g_object_class_install_property (gobject_class, PROP_MODE,
191       g_param_spec_enum ("mode", "Mode", "Mode",
192           GST_TYPE_DECKLINK_MODE, GST_DECKLINK_MODE_NTSC,
193           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
194               G_PARAM_CONSTRUCT)));
195
196   g_object_class_install_property (gobject_class, PROP_CONNECTION,
197       g_param_spec_enum ("connection", "Connection", "Connection",
198           GST_TYPE_DECKLINK_CONNECTION, GST_DECKLINK_CONNECTION_SDI,
199           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
200               G_PARAM_CONSTRUCT)));
201
202   g_object_class_install_property (gobject_class, PROP_AUDIO_INPUT,
203       g_param_spec_enum ("audio-input", "Audio Input", "Audio Input Connection",
204           GST_TYPE_DECKLINK_AUDIO_CONNECTION,
205           GST_DECKLINK_AUDIO_CONNECTION_AUTO,
206           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
207               G_PARAM_CONSTRUCT)));
208
209   g_object_class_install_property (gobject_class, PROP_SUBDEVICE,
210       g_param_spec_int ("subdevice", "Subdevice", "Subdevice",
211           0, 3, 0,
212           (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
213               G_PARAM_CONSTRUCT)));
214 }
215
216 static void
217 gst_decklink_src_init (GstDecklinkSrc * decklinksrc,
218     GstDecklinkSrcClass * decklinksrc_class)
219 {
220   g_static_rec_mutex_init (&decklinksrc->task_mutex);
221   decklinksrc->task = gst_task_create (gst_decklink_src_task, decklinksrc);
222   gst_task_set_lock (decklinksrc->task, &decklinksrc->task_mutex);
223
224   decklinksrc->audiosrcpad =
225       gst_pad_new_from_static_template (&gst_decklink_src_audio_src_template,
226       "audiosrc");
227   gst_pad_set_getcaps_function (decklinksrc->audiosrcpad,
228       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_getcaps));
229   gst_pad_set_setcaps_function (decklinksrc->audiosrcpad,
230       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_setcaps));
231   gst_pad_set_acceptcaps_function (decklinksrc->audiosrcpad,
232       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_acceptcaps));
233   gst_pad_set_fixatecaps_function (decklinksrc->audiosrcpad,
234       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_fixatecaps));
235   gst_pad_set_activate_function (decklinksrc->audiosrcpad,
236       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activate));
237   gst_pad_set_activatepush_function (decklinksrc->audiosrcpad,
238       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activatepush));
239   gst_pad_set_activatepull_function (decklinksrc->audiosrcpad,
240       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activatepull));
241   gst_pad_set_link_function (decklinksrc->audiosrcpad,
242       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_link));
243   gst_pad_set_getrange_function (decklinksrc->audiosrcpad,
244       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_getrange));
245   gst_pad_set_event_function (decklinksrc->audiosrcpad,
246       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_event));
247   gst_pad_set_query_function (decklinksrc->audiosrcpad,
248       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_query));
249   gst_pad_set_iterate_internal_links_function (decklinksrc->audiosrcpad,
250       GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_iterintlink));
251   gst_element_add_pad (GST_ELEMENT (decklinksrc), decklinksrc->audiosrcpad);
252
253
254
255   decklinksrc->videosrcpad =
256       gst_pad_new_from_template (gst_element_class_get_pad_template
257       (GST_ELEMENT_CLASS (decklinksrc_class), "videosrc"), "videosrc");
258   gst_pad_set_getcaps_function (decklinksrc->videosrcpad,
259       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_getcaps));
260   gst_pad_set_setcaps_function (decklinksrc->videosrcpad,
261       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_setcaps));
262   gst_pad_set_acceptcaps_function (decklinksrc->videosrcpad,
263       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_acceptcaps));
264   gst_pad_set_fixatecaps_function (decklinksrc->videosrcpad,
265       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_fixatecaps));
266   gst_pad_set_activate_function (decklinksrc->videosrcpad,
267       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activate));
268   gst_pad_set_activatepush_function (decklinksrc->videosrcpad,
269       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activatepush));
270   gst_pad_set_activatepull_function (decklinksrc->videosrcpad,
271       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activatepull));
272   gst_pad_set_link_function (decklinksrc->videosrcpad,
273       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_link));
274   gst_pad_set_getrange_function (decklinksrc->videosrcpad,
275       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_getrange));
276   gst_pad_set_event_function (decklinksrc->videosrcpad,
277       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_event));
278   gst_pad_set_query_function (decklinksrc->videosrcpad,
279       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_query));
280   gst_pad_set_iterate_internal_links_function (decklinksrc->videosrcpad,
281       GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_iterintlink));
282   gst_element_add_pad (GST_ELEMENT (decklinksrc), decklinksrc->videosrcpad);
283
284
285   decklinksrc->cond = g_cond_new ();
286   decklinksrc->mutex = g_mutex_new ();
287
288   decklinksrc->copy_data = TRUE;
289   decklinksrc->mode = GST_DECKLINK_MODE_NTSC;
290   decklinksrc->connection = GST_DECKLINK_CONNECTION_SDI;
291   decklinksrc->audio_connection = GST_DECKLINK_AUDIO_CONNECTION_AUTO;
292   decklinksrc->subdevice = 0;
293
294   decklinksrc->stop = FALSE;
295   decklinksrc->dropped_frames = 0;
296   decklinksrc->dropped_frames_old = 0;
297   decklinksrc->frame_num = -1; /* -1 so will be 0 after incrementing */
298
299 #ifdef _MSC_VER
300   decklinksrc->com_init_lock = g_mutex_new();
301   decklinksrc->com_deinit_lock = g_mutex_new();
302   decklinksrc->com_initialized = g_cond_new();
303   decklinksrc->com_uninitialize = g_cond_new();
304   decklinksrc->com_uninitialized = g_cond_new();
305
306   g_mutex_lock (decklinksrc->com_init_lock);
307
308   /* create the COM initialization thread */
309   g_thread_create ((GThreadFunc)gst_decklink_src_com_thread,
310     decklinksrc, FALSE, NULL);
311
312   /* wait until the COM thread signals that COM has been initialized */
313   g_cond_wait (decklinksrc->com_initialized, decklinksrc->com_init_lock);
314   g_mutex_unlock (decklinksrc->com_init_lock);
315 #endif /* _MSC_VER */
316 }
317
318 void
319 gst_decklink_src_set_property (GObject * object, guint property_id,
320     const GValue * value, GParamSpec * pspec)
321 {
322   GstDecklinkSrc *decklinksrc;
323
324   g_return_if_fail (GST_IS_DECKLINK_SRC (object));
325   decklinksrc = GST_DECKLINK_SRC (object);
326
327   switch (property_id) {
328     case PROP_MODE:
329       decklinksrc->mode = (GstDecklinkModeEnum) g_value_get_enum (value);
330       break;
331     case PROP_CONNECTION:
332       decklinksrc->connection =
333           (GstDecklinkConnectionEnum) g_value_get_enum (value);
334       break;
335     case PROP_AUDIO_INPUT:
336       decklinksrc->audio_connection =
337           (GstDecklinkAudioConnectionEnum) g_value_get_enum (value);
338       break;
339     case PROP_SUBDEVICE:
340       decklinksrc->subdevice = g_value_get_int (value);
341       break;
342     default:
343       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
344       break;
345   }
346 }
347
348 void
349 gst_decklink_src_get_property (GObject * object, guint property_id,
350     GValue * value, GParamSpec * pspec)
351 {
352   GstDecklinkSrc *decklinksrc;
353
354   g_return_if_fail (GST_IS_DECKLINK_SRC (object));
355   decklinksrc = GST_DECKLINK_SRC (object);
356
357   switch (property_id) {
358     case PROP_MODE:
359       g_value_set_enum (value, decklinksrc->mode);
360       break;
361     case PROP_CONNECTION:
362       g_value_set_enum (value, decklinksrc->connection);
363       break;
364     case PROP_AUDIO_INPUT:
365       g_value_set_enum (value, decklinksrc->audio_connection);
366       break;
367     case PROP_SUBDEVICE:
368       g_value_set_int (value, decklinksrc->subdevice);
369       break;
370     default:
371       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
372       break;
373   }
374 }
375
376 #ifdef _MSC_VER
377 static void
378 gst_decklink_src_com_thread (GstDecklinkSrc * src)
379 {
380   HRESULT res;
381
382   g_mutex_lock (src->com_init_lock);
383
384   /* Initialize COM with a MTA for this process. This thread will
385    * be the first one to enter the apartement and the last one to leave
386    * it, unitializing COM properly */
387
388   res = CoInitializeEx (0, COINIT_MULTITHREADED);
389   if (res == S_FALSE)
390     GST_WARNING_OBJECT (src, "COM has been already initialized in the same process");
391   else if (res == RPC_E_CHANGED_MODE)
392     GST_WARNING_OBJECT (src, "The concurrency model of COM has changed.");
393   else
394     GST_INFO_OBJECT (src, "COM intialized succesfully");
395
396   src->comInitialized = TRUE;
397
398   /* Signal other threads waiting on this condition that COM was initialized */
399   g_cond_signal (src->com_initialized);
400
401   g_mutex_unlock (src->com_init_lock);
402
403   /* Wait until the unitialize condition is met to leave the COM apartement */
404   g_mutex_lock (src->com_deinit_lock);
405   g_cond_wait (src->com_uninitialize, src->com_deinit_lock);
406
407   CoUninitialize ();
408   GST_INFO_OBJECT (src, "COM unintialized succesfully");
409   src->comInitialized = FALSE;
410   g_cond_signal (src->com_uninitialized);
411   g_mutex_unlock (src->com_deinit_lock);
412 }
413 #endif /* _MSC_VER */
414
415 void
416 gst_decklink_src_dispose (GObject * object)
417 {
418   g_return_if_fail (GST_IS_DECKLINK_SRC (object));
419
420   /* clean up as possible.  may be called multiple times */
421
422   G_OBJECT_CLASS (parent_class)->dispose (object);
423 }
424
425 void
426 gst_decklink_src_finalize (GObject * object)
427 {
428   GstDecklinkSrc *decklinksrc;
429
430   g_return_if_fail (GST_IS_DECKLINK_SRC (object));
431   decklinksrc = GST_DECKLINK_SRC (object);
432
433   /* clean up object here */
434
435   g_cond_free (decklinksrc->cond);
436   g_mutex_free (decklinksrc->mutex);
437   gst_task_set_lock (decklinksrc->task, NULL);
438   g_object_unref (decklinksrc->task);
439   if (decklinksrc->audio_caps) {
440     gst_caps_unref (decklinksrc->audio_caps);
441   }
442   if (decklinksrc->video_caps) {
443     gst_caps_unref (decklinksrc->video_caps);
444   }
445
446 #ifdef _MSC_VER
447   /* signal the COM thread that it should uninitialize COM */
448   if (decklinksrc->comInitialized) {
449     g_mutex_lock (decklinksrc->com_deinit_lock);
450     g_cond_signal (decklinksrc->com_uninitialize);
451     g_cond_wait (decklinksrc->com_uninitialized, decklinksrc->com_deinit_lock);
452     g_mutex_unlock (decklinksrc->com_deinit_lock);
453   }
454
455   g_mutex_free (decklinksrc->com_init_lock);
456   g_mutex_free (decklinksrc->com_deinit_lock);
457   g_cond_free (decklinksrc->com_initialized);
458   g_cond_free (decklinksrc->com_uninitialize);
459   g_cond_free (decklinksrc->com_uninitialized);
460 #endif /* _MSC_VER */
461
462   G_OBJECT_CLASS (parent_class)->finalize (object);
463 }
464
465
466
467 static GstPad *
468 gst_decklink_src_request_new_pad (GstElement * element, GstPadTemplate * templ,
469     const gchar * name)
470 {
471
472   return NULL;
473 }
474
475 static void
476 gst_decklink_src_release_pad (GstElement * element, GstPad * pad)
477 {
478
479 }
480
481 static gboolean
482 gst_decklink_src_start (GstElement * element)
483 {
484   GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
485   IDeckLinkIterator *iterator;
486   DeckLinkCaptureDelegate *delegate;
487   //IDeckLinkDisplayModeIterator *mode_iterator;
488   //IDeckLinkDisplayMode *mode;
489   BMDAudioSampleType sample_depth;
490   int channels;
491   HRESULT ret;
492   const GstDecklinkMode *mode;
493   IDeckLinkConfiguration *config;
494   BMDVideoConnection conn;
495   BMDAudioConnection aconn;
496   int i;
497
498   GST_DEBUG_OBJECT (decklinksrc, "start");
499
500   iterator = CreateDeckLinkIteratorInstance ();
501   if (iterator == NULL) {
502     GST_ERROR ("no driver");
503     return FALSE;
504   }
505
506   ret = iterator->Next (&decklinksrc->decklink);
507   if (ret != S_OK) {
508     GST_ERROR ("no card");
509     return FALSE;
510   }
511   for (i = 0; i < decklinksrc->subdevice; i++) {
512     ret = iterator->Next (&decklinksrc->decklink);
513     if (ret != S_OK) {
514       GST_ERROR ("no card");
515       return FALSE;
516     }
517   }
518
519   ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkInput,
520       (void **) &decklinksrc->input);
521   if (ret != S_OK) {
522     GST_ERROR ("query interface failed");
523     return FALSE;
524   }
525
526   delegate = new DeckLinkCaptureDelegate ();
527   delegate->priv = decklinksrc;
528   decklinksrc->input->SetCallback (delegate);
529
530   ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkConfiguration,
531       (void **) &config);
532   if (ret != S_OK) {
533     GST_ERROR ("query interface failed");
534     return FALSE;
535   }
536
537   switch (decklinksrc->connection) {
538     default:
539     case GST_DECKLINK_CONNECTION_SDI:
540       conn = bmdVideoConnectionSDI;
541       aconn = bmdAudioConnectionEmbedded;
542       break;
543     case GST_DECKLINK_CONNECTION_HDMI:
544       conn = bmdVideoConnectionHDMI;
545       aconn = bmdAudioConnectionEmbedded;
546       break;
547     case GST_DECKLINK_CONNECTION_OPTICAL_SDI:
548       conn = bmdVideoConnectionOpticalSDI;
549       aconn = bmdAudioConnectionEmbedded;
550       break;
551     case GST_DECKLINK_CONNECTION_COMPONENT:
552       conn = bmdVideoConnectionComponent;
553       aconn = bmdAudioConnectionAnalog;
554       break;
555     case GST_DECKLINK_CONNECTION_COMPOSITE:
556       conn = bmdVideoConnectionComposite;
557       aconn = bmdAudioConnectionAnalog;
558       break;
559     case GST_DECKLINK_CONNECTION_SVIDEO:
560       conn = bmdVideoConnectionSVideo;
561       aconn = bmdAudioConnectionAnalog;
562       break;
563   }
564
565   ret = config->SetInt (bmdDeckLinkConfigVideoInputConnection, conn);
566   if (ret != S_OK) {
567     GST_ERROR ("set configuration (input source)");
568     return FALSE;
569   }
570
571   if (decklinksrc->connection == GST_DECKLINK_CONNECTION_COMPOSITE) {
572     ret = config->SetInt (bmdDeckLinkConfigAnalogVideoInputFlags,
573         bmdAnalogVideoFlagCompositeSetup75);
574     if (ret != S_OK) {
575       GST_ERROR ("set configuration (composite setup)");
576       return FALSE;
577     }
578   }
579
580   switch (decklinksrc->audio_connection) {
581     default:
582     case GST_DECKLINK_AUDIO_CONNECTION_AUTO:
583       break;
584     case GST_DECKLINK_AUDIO_CONNECTION_EMBEDDED:
585       aconn = bmdAudioConnectionEmbedded;
586       break;
587     case GST_DECKLINK_AUDIO_CONNECTION_AES_EBU:
588       aconn = bmdAudioConnectionAESEBU;
589       break;
590     case GST_DECKLINK_AUDIO_CONNECTION_ANALOG:
591       aconn = bmdAudioConnectionAnalog;
592       break;
593   }
594   ret = config->SetInt (bmdDeckLinkConfigAudioInputConnection, aconn);
595   if (ret != S_OK) {
596     GST_ERROR ("set configuration (audio input connection)");
597     return FALSE;
598   }
599 #if 0
600   ret = decklinksrc->input->GetDisplayModeIterator (&mode_iterator);
601   if (ret != S_OK) {
602     GST_ERROR ("failed to get display mode iterator");
603     return FALSE;
604   }
605
606   i = 0;
607   while (mode_iterator->Next (&mode) == S_OK) {
608     const char *mode_name;
609
610     mode->GetName (&mode_name);
611
612     GST_DEBUG ("%d: mode name: %s", i, mode_name);
613
614     mode->Release ();
615     i++;
616   }
617 #endif
618
619   mode = gst_decklink_get_mode (decklinksrc->mode);
620
621   ret = decklinksrc->input->EnableVideoInput (mode->mode, bmdFormat8BitYUV, 0);
622   if (ret != S_OK) {
623     GST_ERROR ("enable video input failed");
624     return FALSE;
625   }
626
627   sample_depth = bmdAudioSampleType16bitInteger;
628   channels = 2;
629   ret = decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz,
630       sample_depth, channels);
631   if (ret != S_OK) {
632     GST_ERROR ("enable video input failed");
633     return FALSE;
634   }
635
636   ret = decklinksrc->input->StartStreams ();
637   if (ret != S_OK) {
638     GST_ERROR ("start streams failed");
639     return FALSE;
640   }
641
642   g_static_rec_mutex_lock (&decklinksrc->task_mutex);
643   gst_task_start (decklinksrc->task);
644   g_static_rec_mutex_unlock (&decklinksrc->task_mutex);
645
646   return TRUE;
647 }
648
649 static gboolean
650 gst_decklink_src_stop (GstElement * element)
651 {
652   GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
653
654   gst_task_stop (decklinksrc->task);
655
656   g_mutex_lock (decklinksrc->mutex);
657   decklinksrc->stop = TRUE;
658   g_cond_signal (decklinksrc->cond);
659   g_mutex_unlock (decklinksrc->mutex);
660
661   gst_task_join (decklinksrc->task);
662
663   decklinksrc->input->StopStreams ();
664   decklinksrc->input->DisableVideoInput ();
665   decklinksrc->input->DisableAudioInput ();
666
667   decklinksrc->input->Release ();
668   decklinksrc->input = NULL;
669
670   return TRUE;
671 }
672
673 static GstStateChangeReturn
674 gst_decklink_src_change_state (GstElement * element, GstStateChange transition)
675 {
676   GstStateChangeReturn ret;
677   gboolean no_preroll = FALSE;
678
679   g_return_val_if_fail (GST_IS_DECKLINK_SRC (element),
680       GST_STATE_CHANGE_FAILURE);
681
682   switch (transition) {
683     case GST_STATE_CHANGE_NULL_TO_READY:
684       if (!gst_decklink_src_start (element)) {
685         ret = GST_STATE_CHANGE_FAILURE;
686         goto out;
687       }
688       break;
689     case GST_STATE_CHANGE_READY_TO_PAUSED:
690       no_preroll = TRUE;
691       break;
692     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
693       break;
694     default:
695       break;
696   }
697
698   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
699
700   switch (transition) {
701     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
702       no_preroll = TRUE;
703       break;
704     case GST_STATE_CHANGE_PAUSED_TO_READY:
705       break;
706     case GST_STATE_CHANGE_READY_TO_NULL:
707       gst_decklink_src_stop (element);
708       break;
709     default:
710       break;
711   }
712
713   if (no_preroll && ret == GST_STATE_CHANGE_SUCCESS)
714     ret = GST_STATE_CHANGE_NO_PREROLL;
715
716 out:
717   return ret;
718 }
719
720 static GstClock *
721 gst_decklink_src_provide_clock (GstElement * element)
722 {
723
724   return NULL;
725 }
726
727 static gboolean
728 gst_decklink_src_set_clock (GstElement * element, GstClock * clock)
729 {
730
731   return TRUE;
732 }
733
734 static GstIndex *
735 gst_decklink_src_get_index (GstElement * element)
736 {
737
738   return NULL;
739 }
740
741 static void
742 gst_decklink_src_set_index (GstElement * element, GstIndex * index)
743 {
744
745 }
746
747 static gboolean
748 gst_decklink_src_send_event (GstElement * element, GstEvent * event)
749 {
750
751   return TRUE;
752 }
753
754 static gboolean
755 gst_decklink_src_query (GstElement * element, GstQuery * query)
756 {
757
758   return FALSE;
759 }
760
761 static GstCaps *
762 gst_decklink_src_audio_src_getcaps (GstPad * pad)
763 {
764   GstDecklinkSrc *decklinksrc;
765   GstCaps *caps;
766
767   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
768
769   GST_DEBUG_OBJECT (decklinksrc, "getcaps");
770
771   caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
772
773   gst_object_unref (decklinksrc);
774   return caps;
775 }
776
777 static gboolean
778 gst_decklink_src_audio_src_setcaps (GstPad * pad, GstCaps * caps)
779 {
780   GstDecklinkSrc *decklinksrc;
781
782   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
783
784   GST_DEBUG_OBJECT (decklinksrc, "setcaps");
785
786
787   gst_object_unref (decklinksrc);
788   return TRUE;
789 }
790
791 static gboolean
792 gst_decklink_src_audio_src_acceptcaps (GstPad * pad, GstCaps * caps)
793 {
794   GstDecklinkSrc *decklinksrc;
795
796   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
797
798   GST_DEBUG_OBJECT (decklinksrc, "acceptcaps");
799
800
801   gst_object_unref (decklinksrc);
802   return TRUE;
803 }
804
805 static void
806 gst_decklink_src_audio_src_fixatecaps (GstPad * pad, GstCaps * caps)
807 {
808   GstDecklinkSrc *decklinksrc;
809
810   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
811
812   GST_DEBUG_OBJECT (decklinksrc, "fixatecaps");
813
814
815   gst_object_unref (decklinksrc);
816 }
817
818 static gboolean
819 gst_decklink_src_audio_src_activate (GstPad * pad)
820 {
821   GstDecklinkSrc *decklinksrc;
822   gboolean ret;
823
824   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
825
826   GST_DEBUG_OBJECT (decklinksrc, "activate");
827
828   if (gst_pad_check_pull_range (pad)) {
829     GST_DEBUG_OBJECT (pad, "activating pull");
830     ret = gst_pad_activate_pull (pad, TRUE);
831   } else {
832     GST_DEBUG_OBJECT (pad, "activating push");
833     ret = gst_pad_activate_push (pad, TRUE);
834   }
835
836   gst_object_unref (decklinksrc);
837   return ret;
838 }
839
840 static gboolean
841 gst_decklink_src_audio_src_activatepush (GstPad * pad, gboolean active)
842 {
843   GstDecklinkSrc *decklinksrc;
844
845   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
846
847   GST_DEBUG_OBJECT (decklinksrc, "activatepush");
848
849
850   gst_object_unref (decklinksrc);
851   return TRUE;
852 }
853
854 static gboolean
855 gst_decklink_src_audio_src_activatepull (GstPad * pad, gboolean active)
856 {
857   GstDecklinkSrc *decklinksrc;
858
859   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
860
861   GST_DEBUG_OBJECT (decklinksrc, "activatepull");
862
863
864   gst_object_unref (decklinksrc);
865   return TRUE;
866 }
867
868 static GstPadLinkReturn
869 gst_decklink_src_audio_src_link (GstPad * pad, GstPad * peer)
870 {
871   GstDecklinkSrc *decklinksrc;
872
873   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
874
875   GST_DEBUG_OBJECT (decklinksrc, "link");
876
877
878   gst_object_unref (decklinksrc);
879   return GST_PAD_LINK_OK;
880 }
881
882 static GstFlowReturn
883 gst_decklink_src_audio_src_getrange (GstPad * pad, guint64 offset, guint length,
884     GstBuffer ** buffer)
885 {
886   GstDecklinkSrc *decklinksrc;
887
888   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
889
890   GST_DEBUG_OBJECT (decklinksrc, "getrange");
891
892
893   gst_object_unref (decklinksrc);
894   return GST_FLOW_OK;
895 }
896
897 static gboolean
898 gst_decklink_src_audio_src_event (GstPad * pad, GstEvent * event)
899 {
900   gboolean res;
901   GstDecklinkSrc *decklinksrc;
902
903   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
904
905   GST_DEBUG_OBJECT (decklinksrc, "event");
906
907   switch (GST_EVENT_TYPE (event)) {
908     default:
909       res = gst_pad_event_default (pad, event);
910       break;
911   }
912
913   gst_object_unref (decklinksrc);
914   return res;
915 }
916
917 static gboolean
918 gst_decklink_src_audio_src_query (GstPad * pad, GstQuery * query)
919 {
920   gboolean res;
921   GstDecklinkSrc *decklinksrc;
922
923   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
924
925   GST_DEBUG_OBJECT (decklinksrc, "query");
926
927   switch (GST_QUERY_TYPE (query)) {
928     default:
929       res = gst_pad_query_default (pad, query);
930       break;
931   }
932
933   gst_object_unref (decklinksrc);
934   return res;
935 }
936
937 static GstIterator *
938 gst_decklink_src_audio_src_iterintlink (GstPad * pad)
939 {
940   GstDecklinkSrc *decklinksrc;
941   GstIterator *iter;
942
943   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
944
945   GST_DEBUG_OBJECT (decklinksrc, "iterintlink");
946
947   iter = gst_pad_iterate_internal_links_default (pad);
948
949   gst_object_unref (decklinksrc);
950   return iter;
951 }
952
953
954 static GstCaps *
955 gst_decklink_src_video_src_getcaps (GstPad * pad)
956 {
957   GstDecklinkSrc *decklinksrc;
958   GstCaps *caps;
959
960   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
961
962   GST_DEBUG_OBJECT (decklinksrc, "getcaps");
963
964   caps = gst_decklink_mode_get_caps (decklinksrc->mode);
965
966   gst_object_unref (decklinksrc);
967   return caps;
968 }
969
970 static gboolean
971 gst_decklink_src_video_src_setcaps (GstPad * pad, GstCaps * caps)
972 {
973   GstDecklinkSrc *decklinksrc;
974
975   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
976
977   GST_DEBUG_OBJECT (decklinksrc, "setcaps");
978
979
980   gst_object_unref (decklinksrc);
981   return TRUE;
982 }
983
984 static gboolean
985 gst_decklink_src_video_src_acceptcaps (GstPad * pad, GstCaps * caps)
986 {
987   GstDecklinkSrc *decklinksrc;
988
989   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
990
991   GST_DEBUG_OBJECT (decklinksrc, "acceptcaps");
992
993
994   gst_object_unref (decklinksrc);
995   return TRUE;
996 }
997
998 static void
999 gst_decklink_src_video_src_fixatecaps (GstPad * pad, GstCaps * caps)
1000 {
1001   GstDecklinkSrc *decklinksrc;
1002
1003   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1004
1005   GST_DEBUG_OBJECT (decklinksrc, "fixatecaps");
1006
1007
1008   gst_object_unref (decklinksrc);
1009 }
1010
1011 static gboolean
1012 gst_decklink_src_video_src_activate (GstPad * pad)
1013 {
1014   GstDecklinkSrc *decklinksrc;
1015   gboolean ret;
1016
1017   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1018
1019   GST_DEBUG_OBJECT (decklinksrc, "activate");
1020
1021   if (gst_pad_check_pull_range (pad)) {
1022     GST_DEBUG_OBJECT (pad, "activating pull");
1023     ret = gst_pad_activate_pull (pad, TRUE);
1024   } else {
1025     GST_DEBUG_OBJECT (pad, "activating push");
1026     ret = gst_pad_activate_push (pad, TRUE);
1027   }
1028
1029   gst_object_unref (decklinksrc);
1030   return ret;
1031 }
1032
1033 static gboolean
1034 gst_decklink_src_video_src_activatepush (GstPad * pad, gboolean active)
1035 {
1036   GstDecklinkSrc *decklinksrc;
1037
1038   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1039
1040   GST_DEBUG_OBJECT (decklinksrc, "activatepush");
1041
1042
1043   gst_object_unref (decklinksrc);
1044   return TRUE;
1045 }
1046
1047 static gboolean
1048 gst_decklink_src_video_src_activatepull (GstPad * pad, gboolean active)
1049 {
1050   GstDecklinkSrc *decklinksrc;
1051
1052   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1053
1054   GST_DEBUG_OBJECT (decklinksrc, "activatepull");
1055
1056
1057   gst_object_unref (decklinksrc);
1058   return TRUE;
1059 }
1060
1061 static GstPadLinkReturn
1062 gst_decklink_src_video_src_link (GstPad * pad, GstPad * peer)
1063 {
1064   GstDecklinkSrc *decklinksrc;
1065
1066   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1067
1068   GST_DEBUG_OBJECT (decklinksrc, "link");
1069
1070
1071   gst_object_unref (decklinksrc);
1072   return GST_PAD_LINK_OK;
1073 }
1074
1075 static GstFlowReturn
1076 gst_decklink_src_video_src_getrange (GstPad * pad, guint64 offset, guint length,
1077     GstBuffer ** buffer)
1078 {
1079   GstDecklinkSrc *decklinksrc;
1080
1081   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1082
1083   GST_DEBUG_OBJECT (decklinksrc, "getrange");
1084
1085
1086   gst_object_unref (decklinksrc);
1087   return GST_FLOW_OK;
1088 }
1089
1090 static gboolean
1091 gst_decklink_src_video_src_event (GstPad * pad, GstEvent * event)
1092 {
1093   gboolean res;
1094   GstDecklinkSrc *decklinksrc;
1095
1096   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1097
1098   GST_DEBUG_OBJECT (decklinksrc, "event");
1099
1100   switch (GST_EVENT_TYPE (event)) {
1101     default:
1102       res = gst_pad_event_default (pad, event);
1103       break;
1104   }
1105
1106   gst_object_unref (decklinksrc);
1107   return res;
1108 }
1109
1110 static gboolean
1111 gst_decklink_src_video_src_query (GstPad * pad, GstQuery * query)
1112 {
1113   gboolean res;
1114   GstDecklinkSrc *decklinksrc;
1115
1116   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1117
1118   GST_DEBUG_OBJECT (decklinksrc, "query");
1119
1120   switch (GST_QUERY_TYPE (query)) {
1121     default:
1122       res = gst_pad_query_default (pad, query);
1123       break;
1124   }
1125
1126   gst_object_unref (decklinksrc);
1127   return res;
1128 }
1129
1130 static GstIterator *
1131 gst_decklink_src_video_src_iterintlink (GstPad * pad)
1132 {
1133   GstDecklinkSrc *decklinksrc;
1134   GstIterator *iter;
1135
1136   decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
1137
1138   GST_DEBUG_OBJECT (decklinksrc, "iterintlink");
1139
1140   iter = gst_pad_iterate_internal_links_default (pad);
1141
1142   gst_object_unref (decklinksrc);
1143   return iter;
1144 }
1145
1146
1147 static void
1148 video_frame_free (void *data)
1149 {
1150   IDeckLinkVideoInputFrame *video_frame = (IDeckLinkVideoInputFrame *) data;
1151
1152   video_frame->Release ();
1153 }
1154
1155 static void
1156 gst_decklink_src_task (void *priv)
1157 {
1158   GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
1159   GstBuffer *buffer;
1160   GstBuffer *audio_buffer;
1161   IDeckLinkVideoInputFrame *video_frame;
1162   IDeckLinkAudioInputPacket *audio_frame;
1163   void *data;
1164   int n_samples;
1165   GstFlowReturn ret;
1166   const GstDecklinkMode *mode;
1167
1168   GST_DEBUG_OBJECT (decklinksrc, "task");
1169
1170   g_mutex_lock (decklinksrc->mutex);
1171   while (decklinksrc->video_frame == NULL && !decklinksrc->stop) {
1172     g_cond_wait (decklinksrc->cond, decklinksrc->mutex);
1173   }
1174   video_frame = decklinksrc->video_frame;
1175   audio_frame = decklinksrc->audio_frame;
1176   decklinksrc->video_frame = NULL;
1177   decklinksrc->audio_frame = NULL;
1178   g_mutex_unlock (decklinksrc->mutex);
1179
1180   if (decklinksrc->stop) {
1181     GST_DEBUG ("stopping task");
1182     return;
1183   }
1184
1185   /* warning on dropped frames */
1186   if (decklinksrc->dropped_frames - decklinksrc->dropped_frames_old > 0) {
1187     GST_ELEMENT_WARNING (decklinksrc, RESOURCE, READ,
1188                          ("Dropped %d frame(s), for a total of %d frame(s)",
1189                           decklinksrc->dropped_frames - decklinksrc->dropped_frames_old,
1190                           decklinksrc->dropped_frames),
1191                          (NULL));
1192     decklinksrc->dropped_frames_old = decklinksrc->dropped_frames;
1193   }
1194
1195   mode = gst_decklink_get_mode (decklinksrc->mode);
1196
1197   video_frame->GetBytes (&data);
1198   if (decklinksrc->copy_data) {
1199     buffer = gst_buffer_new_and_alloc (mode->width * mode->height * 2);
1200
1201     memcpy (GST_BUFFER_DATA (buffer), data, mode->width * mode->height * 2);
1202
1203     video_frame->Release ();
1204   } else {
1205     buffer = gst_buffer_new ();
1206     GST_BUFFER_SIZE (buffer) = mode->width * mode->height * 2;
1207
1208     GST_BUFFER_DATA (buffer) = (guint8 *) data;
1209
1210     GST_BUFFER_FREE_FUNC (buffer) = video_frame_free;
1211     GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) video_frame;
1212   }
1213
1214   GST_BUFFER_TIMESTAMP (buffer) =
1215       gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
1216       mode->fps_d, mode->fps_n);
1217   GST_BUFFER_DURATION (buffer) =
1218       gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
1219       mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
1220   GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
1221   GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num;
1222   if (decklinksrc->frame_num == 0) {
1223     GstEvent *event;
1224     gboolean ret;
1225
1226     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1227
1228     event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
1229         GST_CLOCK_TIME_NONE, 0);
1230
1231     ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
1232     if (!ret) {
1233       GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
1234       return;
1235     }
1236   }
1237
1238   if (decklinksrc->video_caps == NULL) {
1239     decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
1240   }
1241   gst_buffer_set_caps (buffer, decklinksrc->video_caps);
1242
1243   ret = gst_pad_push (decklinksrc->videosrcpad, buffer);
1244   if (ret != GST_FLOW_OK) {
1245     GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
1246   }
1247
1248   if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
1249     n_samples = audio_frame->GetSampleFrameCount ();
1250     audio_frame->GetBytes (&data);
1251     audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
1252     memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2);
1253
1254     GST_BUFFER_TIMESTAMP (audio_buffer) =
1255         gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
1256         1, 48000);
1257     GST_BUFFER_DURATION (audio_buffer) =
1258         gst_util_uint64_scale_int ((decklinksrc->num_audio_samples +
1259             n_samples) * GST_SECOND, 1,
1260         48000) - GST_BUFFER_TIMESTAMP (audio_buffer);
1261     decklinksrc->num_audio_samples += n_samples;
1262
1263     if (decklinksrc->audio_caps == NULL) {
1264       decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
1265           "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
1266           "signed", G_TYPE_BOOLEAN, TRUE,
1267           "depth", G_TYPE_INT, 16,
1268           "width", G_TYPE_INT, 16,
1269           "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL);
1270     }
1271     gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps);
1272
1273     ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer);
1274     if (ret != GST_FLOW_OK) {
1275       GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
1276     }
1277   }
1278   audio_frame->Release ();
1279 }