~ubuntu-branches/ubuntu/quantal/gst-plugins-bad0.10/quantal-proposed

« back to all changes in this revision

Viewing changes to sys/decklink/gstdecklinksrc.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2011-07-19 14:32:43 UTC
  • mfrom: (18.4.21 sid)
  • Revision ID: james.westby@ubuntu.com-20110719143243-p7pnkh45akfp0ihk
Tags: 0.10.22-2ubuntu1
* Rebased on debian unstable, remaining changes:
  - debian/gstreamer-plugins-bad.install
    * don't include dtmf, liveadder, rtpmux, autoconvert and shm, we include 
      them in -good

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "gstdecklinksrc.h"
 
40
#include "capture.h"
 
41
#include <string.h>
 
42
 
 
43
GST_DEBUG_CATEGORY_STATIC (gst_decklink_src_debug_category);
 
44
#define GST_CAT_DEFAULT gst_decklink_src_debug_category
 
45
 
 
46
/* prototypes */
 
47
 
 
48
 
 
49
static void gst_decklink_src_set_property (GObject * object,
 
50
    guint property_id, const GValue * value, GParamSpec * pspec);
 
51
static void gst_decklink_src_get_property (GObject * object,
 
52
    guint property_id, GValue * value, GParamSpec * pspec);
 
53
static void gst_decklink_src_dispose (GObject * object);
 
54
static void gst_decklink_src_finalize (GObject * object);
 
55
 
 
56
static GstPad *gst_decklink_src_request_new_pad (GstElement * element,
 
57
    GstPadTemplate * templ, const gchar * name);
 
58
static void gst_decklink_src_release_pad (GstElement * element, GstPad * pad);
 
59
static GstStateChangeReturn
 
60
gst_decklink_src_change_state (GstElement * element, GstStateChange transition);
 
61
static GstClock *gst_decklink_src_provide_clock (GstElement * element);
 
62
static gboolean gst_decklink_src_set_clock (GstElement * element,
 
63
    GstClock * clock);
 
64
static GstIndex *gst_decklink_src_get_index (GstElement * element);
 
65
static void gst_decklink_src_set_index (GstElement * element, GstIndex * index);
 
66
static gboolean gst_decklink_src_send_event (GstElement * element,
 
67
    GstEvent * event);
 
68
static gboolean gst_decklink_src_query (GstElement * element, GstQuery * query);
 
69
 
 
70
static GstCaps *gst_decklink_src_audio_src_getcaps (GstPad * pad);
 
71
static gboolean gst_decklink_src_audio_src_setcaps (GstPad * pad, GstCaps * caps);
 
72
static gboolean gst_decklink_src_audio_src_acceptcaps (GstPad * pad, GstCaps * caps);
 
73
static void gst_decklink_src_audio_src_fixatecaps (GstPad * pad, GstCaps * caps);
 
74
static gboolean gst_decklink_src_audio_src_activate (GstPad * pad);
 
75
static gboolean gst_decklink_src_audio_src_activatepush (GstPad * pad,
 
76
    gboolean active);
 
77
static gboolean gst_decklink_src_audio_src_activatepull (GstPad * pad,
 
78
    gboolean active);
 
79
static GstPadLinkReturn gst_decklink_src_audio_src_link (GstPad * pad, GstPad * peer);
 
80
static GstFlowReturn gst_decklink_src_audio_src_getrange (GstPad * pad,
 
81
    guint64 offset, guint length, GstBuffer ** buffer);
 
82
static gboolean gst_decklink_src_audio_src_event (GstPad * pad, GstEvent * event);
 
83
static gboolean gst_decklink_src_audio_src_query (GstPad * pad, GstQuery * query);
 
84
static GstIterator *gst_decklink_src_audio_src_iterintlink (GstPad * pad);
 
85
 
 
86
 
 
87
static GstCaps *gst_decklink_src_video_src_getcaps (GstPad * pad);
 
88
static gboolean gst_decklink_src_video_src_setcaps (GstPad * pad, GstCaps * caps);
 
89
static gboolean gst_decklink_src_video_src_acceptcaps (GstPad * pad, GstCaps * caps);
 
90
static void gst_decklink_src_video_src_fixatecaps (GstPad * pad, GstCaps * caps);
 
91
static gboolean gst_decklink_src_video_src_activate (GstPad * pad);
 
92
static gboolean gst_decklink_src_video_src_activatepush (GstPad * pad,
 
93
    gboolean active);
 
94
static gboolean gst_decklink_src_video_src_activatepull (GstPad * pad,
 
95
    gboolean active);
 
96
static GstPadLinkReturn gst_decklink_src_video_src_link (GstPad * pad, GstPad * peer);
 
97
static GstFlowReturn gst_decklink_src_video_src_getrange (GstPad * pad,
 
98
    guint64 offset, guint length, GstBuffer ** buffer);
 
99
static gboolean gst_decklink_src_video_src_event (GstPad * pad, GstEvent * event);
 
100
static gboolean gst_decklink_src_video_src_query (GstPad * pad, GstQuery * query);
 
101
static GstIterator *gst_decklink_src_video_src_iterintlink (GstPad * pad);
 
102
 
 
103
static void gst_decklink_src_task (void *priv);
 
104
 
 
105
enum
 
106
{
 
107
  PROP_0
 
108
};
 
109
 
 
110
/* pad templates */
 
111
 
 
112
static GstStaticPadTemplate gst_decklink_src_audio_src_template =
 
113
GST_STATIC_PAD_TEMPLATE ("audiosrc",
 
114
    GST_PAD_SRC,
 
115
    GST_PAD_ALWAYS,
 
116
    GST_STATIC_CAPS ("audio/x-raw-int,width=16,depth=16,channels=2,rate=48000")
 
117
    );
 
118
 
 
119
#define MODE(w,h,n,d,i) \
 
120
  "video/x-raw-yuv,format=(fourcc)UYVY,width=" #w ",height=" #h \
 
121
  ",framerate=" #n "/" #d ",interlaced=" #i
 
122
 
 
123
static GstStaticPadTemplate gst_decklink_src_video_src_template =
 
124
GST_STATIC_PAD_TEMPLATE ("videosrc",
 
125
    GST_PAD_SRC,
 
126
    GST_PAD_ALWAYS,
 
127
    GST_STATIC_CAPS (
 
128
      MODE(720,486,30000,1001,true) ";"
 
129
      MODE(720,486,24000,1001,true) ";"
 
130
      MODE(720,576,25,1,true) ";"
 
131
      MODE(1920,1080,24000,1001,false) ";"
 
132
      MODE(1920,1080,24,1,false) ";"
 
133
      MODE(1920,1080,25,1,false) ";"
 
134
      MODE(1920,1080,30000,1001,false) ";"
 
135
      MODE(1920,1080,30,1,false) ";"
 
136
      MODE(1920,1080,25,1,true) ";"
 
137
      MODE(1920,1080,30000,1001,true) ";"
 
138
      MODE(1920,1080,30,1,true) ";"
 
139
      MODE(1280,720,50,1,true) ";"
 
140
      MODE(1280,720,60000,1001,true) ";"
 
141
      MODE(1280,720,60,1,true)
 
142
    ));
 
143
 
 
144
typedef struct _DecklinkMode DecklinkMode;
 
145
struct _DecklinkMode {
 
146
  BMDDisplayMode mode;
 
147
  int width;
 
148
  int height;
 
149
  int fps_n;
 
150
  int fps_d;
 
151
  gboolean interlaced;
 
152
};
 
153
 
 
154
static DecklinkMode modes[] = {
 
155
  { bmdModeNTSC, 720,486,30000,1001,true },
 
156
  { bmdModeNTSC2398, 720,486,24000,1001,true },
 
157
  { bmdModePAL, 720,576,25,1,true },
 
158
  { bmdModeHD1080p2398, 1920,1080,24000,1001,false },
 
159
  { bmdModeHD1080p24, 1920,1080,24,1,false },
 
160
  { bmdModeHD1080p25, 1920,1080,25,1,false },
 
161
  { bmdModeHD1080p2997, 1920,1080,30000,1001,false },
 
162
  { bmdModeHD1080p30, 1920,1080,30,1,false },
 
163
  { bmdModeHD1080i50, 1920,1080,25,1,true },
 
164
  { bmdModeHD1080i5994, 1920,1080,30000,1001,true },
 
165
  { bmdModeHD1080i6000, 1920,1080,30,1,true },
 
166
  { bmdModeHD720p50, 1280,720,50,1,true },
 
167
  { bmdModeHD720p5994, 1280,720,60000,1001,true },
 
168
  { bmdModeHD720p60, 1280,720,60,1,true }
 
169
};
 
170
 
 
171
 
 
172
/* class initialization */
 
173
 
 
174
#define DEBUG_INIT(bla) \
 
175
  GST_DEBUG_CATEGORY_INIT (gst_decklink_src_debug_category, "decklinksrc", 0, \
 
176
      "debug category for decklinksrc element");
 
177
 
 
178
GST_BOILERPLATE_FULL (GstDecklinkSrc, gst_decklink_src, GstElement,
 
179
    GST_TYPE_ELEMENT, DEBUG_INIT);
 
180
 
 
181
static void
 
182
gst_decklink_src_base_init (gpointer g_class)
 
183
{
 
184
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
185
 
 
186
  gst_element_class_add_pad_template (element_class,
 
187
      gst_static_pad_template_get (&gst_decklink_src_audio_src_template));
 
188
  gst_element_class_add_pad_template (element_class,
 
189
      gst_static_pad_template_get (&gst_decklink_src_video_src_template));
 
190
 
 
191
  gst_element_class_set_details_simple (element_class, "Decklink source",
 
192
      "Source/Video", "DeckLink Source", "David Schleef <ds@entropywave.com>");
 
193
}
 
194
 
 
195
static void
 
196
gst_decklink_src_class_init (GstDecklinkSrcClass * klass)
 
197
{
 
198
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
199
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
200
 
 
201
  gobject_class->set_property = gst_decklink_src_set_property;
 
202
  gobject_class->get_property = gst_decklink_src_get_property;
 
203
  gobject_class->dispose = gst_decklink_src_dispose;
 
204
  gobject_class->finalize = gst_decklink_src_finalize;
 
205
  element_class->request_new_pad =
 
206
      GST_DEBUG_FUNCPTR (gst_decklink_src_request_new_pad);
 
207
  element_class->release_pad = GST_DEBUG_FUNCPTR (gst_decklink_src_release_pad);
 
208
  element_class->change_state =
 
209
      GST_DEBUG_FUNCPTR (gst_decklink_src_change_state);
 
210
  element_class->provide_clock =
 
211
      GST_DEBUG_FUNCPTR (gst_decklink_src_provide_clock);
 
212
  element_class->set_clock = GST_DEBUG_FUNCPTR (gst_decklink_src_set_clock);
 
213
  element_class->get_index = GST_DEBUG_FUNCPTR (gst_decklink_src_get_index);
 
214
  element_class->set_index = GST_DEBUG_FUNCPTR (gst_decklink_src_set_index);
 
215
  element_class->send_event = GST_DEBUG_FUNCPTR (gst_decklink_src_send_event);
 
216
  element_class->query = GST_DEBUG_FUNCPTR (gst_decklink_src_query);
 
217
 
 
218
}
 
219
 
 
220
static void
 
221
gst_decklink_src_init (GstDecklinkSrc * decklinksrc,
 
222
    GstDecklinkSrcClass * decklinksrc_class)
 
223
{
 
224
  g_static_rec_mutex_init (&decklinksrc->task_mutex);
 
225
  decklinksrc->task = gst_task_create (gst_decklink_src_task, decklinksrc);
 
226
  gst_task_set_lock (decklinksrc->task, &decklinksrc->task_mutex);
 
227
 
 
228
  decklinksrc->audiosrcpad =
 
229
      gst_pad_new_from_static_template (&gst_decklink_src_audio_src_template, "audiosrc");
 
230
  gst_pad_set_getcaps_function (decklinksrc->audiosrcpad,
 
231
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_getcaps));
 
232
  gst_pad_set_setcaps_function (decklinksrc->audiosrcpad,
 
233
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_setcaps));
 
234
  gst_pad_set_acceptcaps_function (decklinksrc->audiosrcpad,
 
235
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_acceptcaps));
 
236
  gst_pad_set_fixatecaps_function (decklinksrc->audiosrcpad,
 
237
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_fixatecaps));
 
238
  gst_pad_set_activate_function (decklinksrc->audiosrcpad,
 
239
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activate));
 
240
  gst_pad_set_activatepush_function (decklinksrc->audiosrcpad,
 
241
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activatepush));
 
242
  gst_pad_set_activatepull_function (decklinksrc->audiosrcpad,
 
243
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_activatepull));
 
244
  gst_pad_set_link_function (decklinksrc->audiosrcpad,
 
245
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_link));
 
246
  gst_pad_set_getrange_function (decklinksrc->audiosrcpad,
 
247
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_getrange));
 
248
  gst_pad_set_event_function (decklinksrc->audiosrcpad,
 
249
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_event));
 
250
  gst_pad_set_query_function (decklinksrc->audiosrcpad,
 
251
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_query));
 
252
  gst_pad_set_iterate_internal_links_function (decklinksrc->audiosrcpad,
 
253
      GST_DEBUG_FUNCPTR (gst_decklink_src_audio_src_iterintlink));
 
254
  gst_element_add_pad (GST_ELEMENT (decklinksrc), decklinksrc->audiosrcpad);
 
255
 
 
256
 
 
257
 
 
258
  decklinksrc->videosrcpad =
 
259
      gst_pad_new_from_static_template (&gst_decklink_src_video_src_template, "videosrc");
 
260
  gst_pad_set_getcaps_function (decklinksrc->videosrcpad,
 
261
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_getcaps));
 
262
  gst_pad_set_setcaps_function (decklinksrc->videosrcpad,
 
263
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_setcaps));
 
264
  gst_pad_set_acceptcaps_function (decklinksrc->videosrcpad,
 
265
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_acceptcaps));
 
266
  gst_pad_set_fixatecaps_function (decklinksrc->videosrcpad,
 
267
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_fixatecaps));
 
268
  gst_pad_set_activate_function (decklinksrc->videosrcpad,
 
269
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activate));
 
270
  gst_pad_set_activatepush_function (decklinksrc->videosrcpad,
 
271
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activatepush));
 
272
  gst_pad_set_activatepull_function (decklinksrc->videosrcpad,
 
273
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_activatepull));
 
274
  gst_pad_set_link_function (decklinksrc->videosrcpad,
 
275
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_link));
 
276
  gst_pad_set_getrange_function (decklinksrc->videosrcpad,
 
277
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_getrange));
 
278
  gst_pad_set_event_function (decklinksrc->videosrcpad,
 
279
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_event));
 
280
  gst_pad_set_query_function (decklinksrc->videosrcpad,
 
281
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_query));
 
282
  gst_pad_set_iterate_internal_links_function (decklinksrc->videosrcpad,
 
283
      GST_DEBUG_FUNCPTR (gst_decklink_src_video_src_iterintlink));
 
284
  gst_element_add_pad (GST_ELEMENT (decklinksrc), decklinksrc->videosrcpad);
 
285
 
 
286
 
 
287
  decklinksrc->cond = g_cond_new();
 
288
  decklinksrc->mutex = g_mutex_new();
 
289
 
 
290
  decklinksrc->copy_data = TRUE;
 
291
  decklinksrc->mode = 0;
 
292
 
 
293
  decklinksrc->width = modes[decklinksrc->mode].width;
 
294
  decklinksrc->height = modes[decklinksrc->mode].height;
 
295
  decklinksrc->fps_n = modes[decklinksrc->mode].fps_n;
 
296
  decklinksrc->fps_d = modes[decklinksrc->mode].fps_d;
 
297
  decklinksrc->interlaced = modes[decklinksrc->mode].interlaced;
 
298
  decklinksrc->bmd_mode = modes[decklinksrc->mode].mode;
 
299
 
 
300
}
 
301
 
 
302
void
 
303
gst_decklink_src_set_property (GObject * object, guint property_id,
 
304
    const GValue * value, GParamSpec * pspec)
 
305
{
 
306
  GstDecklinkSrc *decklinksrc;
 
307
 
 
308
  g_return_if_fail (GST_IS_DECKLINK_SRC (object));
 
309
  decklinksrc = GST_DECKLINK_SRC (object);
 
310
 
 
311
  switch (property_id) {
 
312
    default:
 
313
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
314
      break;
 
315
  }
 
316
}
 
317
 
 
318
void
 
319
gst_decklink_src_get_property (GObject * object, guint property_id,
 
320
    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
    default:
 
329
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
330
      break;
 
331
  }
 
332
}
 
333
 
 
334
void
 
335
gst_decklink_src_dispose (GObject * object)
 
336
{
 
337
  GstDecklinkSrc *decklinksrc;
 
338
 
 
339
  g_return_if_fail (GST_IS_DECKLINK_SRC (object));
 
340
  decklinksrc = GST_DECKLINK_SRC (object);
 
341
 
 
342
  /* clean up as possible.  may be called multiple times */
 
343
 
 
344
  G_OBJECT_CLASS (parent_class)->dispose (object);
 
345
}
 
346
 
 
347
void
 
348
gst_decklink_src_finalize (GObject * object)
 
349
{
 
350
  GstDecklinkSrc *decklinksrc;
 
351
 
 
352
  g_return_if_fail (GST_IS_DECKLINK_SRC (object));
 
353
  decklinksrc = GST_DECKLINK_SRC (object);
 
354
 
 
355
  /* clean up object here */
 
356
 
 
357
  g_cond_free (decklinksrc->cond);
 
358
  g_mutex_free (decklinksrc->mutex);
 
359
  gst_task_set_lock (decklinksrc->task, NULL);
 
360
  g_object_unref (decklinksrc->task);
 
361
  if (decklinksrc->audio_caps) {
 
362
    gst_caps_unref (decklinksrc->audio_caps);
 
363
  }
 
364
  if (decklinksrc->video_caps) {
 
365
    gst_caps_unref (decklinksrc->video_caps);
 
366
  }
 
367
 
 
368
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
369
}
 
370
 
 
371
 
 
372
 
 
373
static GstPad *
 
374
gst_decklink_src_request_new_pad (GstElement * element, GstPadTemplate * templ,
 
375
    const gchar * name)
 
376
{
 
377
 
 
378
  return NULL;
 
379
}
 
380
 
 
381
static void
 
382
gst_decklink_src_release_pad (GstElement * element, GstPad * pad)
 
383
{
 
384
 
 
385
}
 
386
 
 
387
static gboolean
 
388
gst_decklink_src_start (GstElement * element)
 
389
{
 
390
  GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
 
391
  IDeckLinkIterator *iterator;
 
392
  DeckLinkCaptureDelegate *delegate;
 
393
  IDeckLinkDisplayModeIterator *mode_iterator;
 
394
  IDeckLinkDisplayMode *mode;
 
395
  int i;
 
396
  int sample_depth;
 
397
  int channels;
 
398
  BMDVideoInputFlags input_flags;
 
399
  BMDDisplayMode selected_mode;
 
400
  BMDPixelFormat pixel_format;
 
401
  HRESULT ret;
 
402
 
 
403
  GST_DEBUG_OBJECT (decklinksrc, "start");
 
404
 
 
405
  iterator = CreateDeckLinkIteratorInstance ();
 
406
  if (iterator == NULL) {
 
407
    GST_ERROR("no driver");
 
408
    return FALSE;
 
409
  }
 
410
 
 
411
  ret = iterator->Next (&decklinksrc->decklink);
 
412
  if (ret != S_OK) {
 
413
    GST_ERROR("no card");
 
414
    return FALSE;
 
415
  }
 
416
 
 
417
  ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkInput,
 
418
      (void **) &decklinksrc->input);
 
419
  if (ret != S_OK) {
 
420
    GST_ERROR ("query interface failed");
 
421
    return FALSE;
 
422
  }
 
423
 
 
424
  delegate = new DeckLinkCaptureDelegate ();
 
425
  delegate->priv = decklinksrc;
 
426
  decklinksrc->input->SetCallback (delegate);
 
427
 
 
428
  ret = decklinksrc->input->GetDisplayModeIterator (&mode_iterator);
 
429
  if (ret != S_OK) {
 
430
    GST_ERROR("failed to get display mode iterator");
 
431
    return FALSE;
 
432
  }
 
433
 
 
434
  i = 0;
 
435
  while (mode_iterator->Next (&mode) == S_OK) {
 
436
    const char *mode_name;
 
437
 
 
438
    mode->GetName (&mode_name);
 
439
 
 
440
    GST_ERROR("%d: mode name: %s", i, mode_name);
 
441
 
 
442
    mode->Release ();
 
443
    i++;
 
444
  }
 
445
 
 
446
  pixel_format = bmdFormat8BitYUV;
 
447
  selected_mode = decklinksrc->bmd_mode;
 
448
  input_flags = 0;
 
449
  ret = decklinksrc->input->EnableVideoInput (selected_mode, pixel_format,
 
450
      input_flags);
 
451
  if (ret != S_OK){
 
452
    GST_ERROR("enable video input failed");
 
453
    return FALSE;
 
454
  }
 
455
 
 
456
  sample_depth = 16;
 
457
  channels = 2;
 
458
  ret = decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz, sample_depth,
 
459
      channels);
 
460
  if (ret != S_OK){
 
461
    GST_ERROR("enable video input failed");
 
462
    return FALSE;
 
463
  }
 
464
 
 
465
  ret = decklinksrc->input->StartStreams ();
 
466
  if (ret != S_OK) {
 
467
    GST_ERROR("start streams failed");
 
468
    return FALSE;
 
469
  }
 
470
 
 
471
  g_static_rec_mutex_lock (&decklinksrc->task_mutex);
 
472
  gst_task_start (decklinksrc->task);
 
473
  g_static_rec_mutex_unlock (&decklinksrc->task_mutex);
 
474
 
 
475
  return TRUE;
 
476
}
 
477
 
 
478
static gboolean
 
479
gst_decklink_src_stop (GstElement * element)
 
480
{
 
481
  GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
 
482
 
 
483
  gst_task_stop (decklinksrc->task);
 
484
 
 
485
  g_mutex_lock (decklinksrc->mutex);
 
486
  decklinksrc->stop = TRUE;
 
487
  g_cond_signal (decklinksrc->cond);
 
488
  g_mutex_unlock (decklinksrc->mutex);
 
489
 
 
490
  gst_task_join (decklinksrc->task);
 
491
 
 
492
  return TRUE;
 
493
}
 
494
 
 
495
static GstStateChangeReturn
 
496
gst_decklink_src_change_state (GstElement * element, GstStateChange transition)
 
497
{
 
498
  GstDecklinkSrc *decklinksrc;
 
499
  GstStateChangeReturn ret;
 
500
  gboolean no_preroll = FALSE;
 
501
 
 
502
  g_return_val_if_fail (GST_IS_DECKLINK_SRC (element),
 
503
      GST_STATE_CHANGE_FAILURE);
 
504
  decklinksrc = GST_DECKLINK_SRC (element);
 
505
 
 
506
  switch (transition) {
 
507
    case GST_STATE_CHANGE_NULL_TO_READY:
 
508
      if (!gst_decklink_src_start (element)) {
 
509
        ret = GST_STATE_CHANGE_FAILURE;
 
510
        goto out;
 
511
      }
 
512
      break;
 
513
    case GST_STATE_CHANGE_READY_TO_PAUSED:
 
514
      no_preroll = TRUE;
 
515
      break;
 
516
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
 
517
      break;
 
518
    default:
 
519
      break;
 
520
  }
 
521
 
 
522
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
523
 
 
524
  switch (transition) {
 
525
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
 
526
      no_preroll = TRUE;
 
527
      break;
 
528
    case GST_STATE_CHANGE_PAUSED_TO_READY:
 
529
      break;
 
530
    case GST_STATE_CHANGE_READY_TO_NULL:
 
531
      gst_decklink_src_stop (element);
 
532
      break;
 
533
    default:
 
534
      break;
 
535
  }
 
536
 
 
537
  if (no_preroll && ret == GST_STATE_CHANGE_SUCCESS)
 
538
    ret = GST_STATE_CHANGE_NO_PREROLL;
 
539
 
 
540
out:
 
541
  return ret;
 
542
}
 
543
 
 
544
static GstClock *
 
545
gst_decklink_src_provide_clock (GstElement * element)
 
546
{
 
547
 
 
548
  return NULL;
 
549
}
 
550
 
 
551
static gboolean
 
552
gst_decklink_src_set_clock (GstElement * element, GstClock * clock)
 
553
{
 
554
 
 
555
  return TRUE;
 
556
}
 
557
 
 
558
static GstIndex *
 
559
gst_decklink_src_get_index (GstElement * element)
 
560
{
 
561
 
 
562
  return NULL;
 
563
}
 
564
 
 
565
static void
 
566
gst_decklink_src_set_index (GstElement * element, GstIndex * index)
 
567
{
 
568
 
 
569
}
 
570
 
 
571
static gboolean
 
572
gst_decklink_src_send_event (GstElement * element, GstEvent * event)
 
573
{
 
574
 
 
575
  return TRUE;
 
576
}
 
577
 
 
578
static gboolean
 
579
gst_decklink_src_query (GstElement * element, GstQuery * query)
 
580
{
 
581
 
 
582
  return FALSE;
 
583
}
 
584
 
 
585
static GstCaps *
 
586
gst_decklink_src_audio_src_getcaps (GstPad * pad)
 
587
{
 
588
  GstDecklinkSrc *decklinksrc;
 
589
  GstCaps *caps;
 
590
 
 
591
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
592
 
 
593
  GST_DEBUG_OBJECT (decklinksrc, "getcaps");
 
594
 
 
595
  caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
 
596
 
 
597
  gst_object_unref (decklinksrc);
 
598
  return caps;
 
599
}
 
600
 
 
601
static gboolean
 
602
gst_decklink_src_audio_src_setcaps (GstPad * pad, GstCaps * caps)
 
603
{
 
604
  GstDecklinkSrc *decklinksrc;
 
605
 
 
606
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
607
 
 
608
  GST_DEBUG_OBJECT (decklinksrc, "setcaps");
 
609
 
 
610
 
 
611
  gst_object_unref (decklinksrc);
 
612
  return TRUE;
 
613
}
 
614
 
 
615
static gboolean
 
616
gst_decklink_src_audio_src_acceptcaps (GstPad * pad, GstCaps * caps)
 
617
{
 
618
  GstDecklinkSrc *decklinksrc;
 
619
 
 
620
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
621
 
 
622
  GST_DEBUG_OBJECT (decklinksrc, "acceptcaps");
 
623
 
 
624
 
 
625
  gst_object_unref (decklinksrc);
 
626
  return TRUE;
 
627
}
 
628
 
 
629
static void
 
630
gst_decklink_src_audio_src_fixatecaps (GstPad * pad, GstCaps * caps)
 
631
{
 
632
  GstDecklinkSrc *decklinksrc;
 
633
 
 
634
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
635
 
 
636
  GST_DEBUG_OBJECT (decklinksrc, "fixatecaps");
 
637
 
 
638
 
 
639
  gst_object_unref (decklinksrc);
 
640
}
 
641
 
 
642
static gboolean
 
643
gst_decklink_src_audio_src_activate (GstPad * pad)
 
644
{
 
645
  GstDecklinkSrc *decklinksrc;
 
646
  gboolean ret;
 
647
 
 
648
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
649
 
 
650
  GST_DEBUG_OBJECT (decklinksrc, "activate");
 
651
 
 
652
  if (gst_pad_check_pull_range (pad)) {
 
653
    GST_DEBUG_OBJECT (pad, "activating pull");
 
654
    ret = gst_pad_activate_pull (pad, TRUE);
 
655
  } else {
 
656
    GST_DEBUG_OBJECT (pad, "activating push");
 
657
    ret = gst_pad_activate_push (pad, TRUE);
 
658
  }
 
659
 
 
660
  gst_object_unref (decklinksrc);
 
661
  return ret;
 
662
}
 
663
 
 
664
static gboolean
 
665
gst_decklink_src_audio_src_activatepush (GstPad * pad, gboolean active)
 
666
{
 
667
  GstDecklinkSrc *decklinksrc;
 
668
 
 
669
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
670
 
 
671
  GST_DEBUG_OBJECT (decklinksrc, "activatepush");
 
672
 
 
673
 
 
674
  gst_object_unref (decklinksrc);
 
675
  return TRUE;
 
676
}
 
677
 
 
678
static gboolean
 
679
gst_decklink_src_audio_src_activatepull (GstPad * pad, gboolean active)
 
680
{
 
681
  GstDecklinkSrc *decklinksrc;
 
682
 
 
683
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
684
 
 
685
  GST_DEBUG_OBJECT (decklinksrc, "activatepull");
 
686
 
 
687
 
 
688
  gst_object_unref (decklinksrc);
 
689
  return TRUE;
 
690
}
 
691
 
 
692
static GstPadLinkReturn
 
693
gst_decklink_src_audio_src_link (GstPad * pad, GstPad * peer)
 
694
{
 
695
  GstDecklinkSrc *decklinksrc;
 
696
 
 
697
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
698
 
 
699
  GST_DEBUG_OBJECT (decklinksrc, "link");
 
700
 
 
701
 
 
702
  gst_object_unref (decklinksrc);
 
703
  return GST_PAD_LINK_OK;
 
704
}
 
705
 
 
706
static GstFlowReturn
 
707
gst_decklink_src_audio_src_getrange (GstPad * pad, guint64 offset, guint length,
 
708
    GstBuffer ** buffer)
 
709
{
 
710
  GstDecklinkSrc *decklinksrc;
 
711
 
 
712
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
713
 
 
714
  GST_DEBUG_OBJECT (decklinksrc, "getrange");
 
715
 
 
716
 
 
717
  gst_object_unref (decklinksrc);
 
718
  return GST_FLOW_OK;
 
719
}
 
720
 
 
721
static gboolean
 
722
gst_decklink_src_audio_src_event (GstPad * pad, GstEvent * event)
 
723
{
 
724
  gboolean res;
 
725
  GstDecklinkSrc *decklinksrc;
 
726
 
 
727
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
728
 
 
729
  GST_DEBUG_OBJECT (decklinksrc, "event");
 
730
 
 
731
  switch (GST_EVENT_TYPE (event)) {
 
732
    default:
 
733
      res = gst_pad_event_default (pad, event);
 
734
      break;
 
735
  }
 
736
 
 
737
  gst_object_unref (decklinksrc);
 
738
  return res;
 
739
}
 
740
 
 
741
static gboolean
 
742
gst_decklink_src_audio_src_query (GstPad * pad, GstQuery * query)
 
743
{
 
744
  gboolean res;
 
745
  GstDecklinkSrc *decklinksrc;
 
746
 
 
747
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
748
 
 
749
  GST_DEBUG_OBJECT (decklinksrc, "query");
 
750
 
 
751
  switch (GST_QUERY_TYPE (query)) {
 
752
    default:
 
753
      res = gst_pad_query_default (pad, query);
 
754
      break;
 
755
  }
 
756
 
 
757
  gst_object_unref (decklinksrc);
 
758
  return res;
 
759
}
 
760
 
 
761
static GstIterator *
 
762
gst_decklink_src_audio_src_iterintlink (GstPad * pad)
 
763
{
 
764
  GstDecklinkSrc *decklinksrc;
 
765
  GstIterator *iter;
 
766
 
 
767
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
768
 
 
769
  GST_DEBUG_OBJECT (decklinksrc, "iterintlink");
 
770
 
 
771
  iter = gst_pad_iterate_internal_links_default (pad);
 
772
 
 
773
  gst_object_unref (decklinksrc);
 
774
  return iter;
 
775
}
 
776
 
 
777
 
 
778
static GstCaps *
 
779
gst_decklink_src_video_src_getcaps (GstPad * pad)
 
780
{
 
781
  GstDecklinkSrc *decklinksrc;
 
782
  GstCaps *caps;
 
783
 
 
784
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
785
 
 
786
  GST_DEBUG_OBJECT (decklinksrc, "getcaps");
 
787
 
 
788
  caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
 
789
 
 
790
  gst_object_unref (decklinksrc);
 
791
  return caps;
 
792
}
 
793
 
 
794
static gboolean
 
795
gst_decklink_src_video_src_setcaps (GstPad * pad, GstCaps * caps)
 
796
{
 
797
  GstDecklinkSrc *decklinksrc;
 
798
 
 
799
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
800
 
 
801
  GST_DEBUG_OBJECT (decklinksrc, "setcaps");
 
802
 
 
803
 
 
804
  gst_object_unref (decklinksrc);
 
805
  return TRUE;
 
806
}
 
807
 
 
808
static gboolean
 
809
gst_decklink_src_video_src_acceptcaps (GstPad * pad, GstCaps * caps)
 
810
{
 
811
  GstDecklinkSrc *decklinksrc;
 
812
 
 
813
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
814
 
 
815
  GST_DEBUG_OBJECT (decklinksrc, "acceptcaps");
 
816
 
 
817
 
 
818
  gst_object_unref (decklinksrc);
 
819
  return TRUE;
 
820
}
 
821
 
 
822
static void
 
823
gst_decklink_src_video_src_fixatecaps (GstPad * pad, GstCaps * caps)
 
824
{
 
825
  GstDecklinkSrc *decklinksrc;
 
826
 
 
827
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
828
 
 
829
  GST_DEBUG_OBJECT (decklinksrc, "fixatecaps");
 
830
 
 
831
 
 
832
  gst_object_unref (decklinksrc);
 
833
}
 
834
 
 
835
static gboolean
 
836
gst_decklink_src_video_src_activate (GstPad * pad)
 
837
{
 
838
  GstDecklinkSrc *decklinksrc;
 
839
  gboolean ret;
 
840
 
 
841
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
842
 
 
843
  GST_DEBUG_OBJECT (decklinksrc, "activate");
 
844
 
 
845
  if (gst_pad_check_pull_range (pad)) {
 
846
    GST_DEBUG_OBJECT (pad, "activating pull");
 
847
    ret = gst_pad_activate_pull (pad, TRUE);
 
848
  } else {
 
849
    GST_DEBUG_OBJECT (pad, "activating push");
 
850
    ret = gst_pad_activate_push (pad, TRUE);
 
851
  }
 
852
 
 
853
  gst_object_unref (decklinksrc);
 
854
  return ret;
 
855
}
 
856
 
 
857
static gboolean
 
858
gst_decklink_src_video_src_activatepush (GstPad * pad, gboolean active)
 
859
{
 
860
  GstDecklinkSrc *decklinksrc;
 
861
 
 
862
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
863
 
 
864
  GST_DEBUG_OBJECT (decklinksrc, "activatepush");
 
865
 
 
866
 
 
867
  gst_object_unref (decklinksrc);
 
868
  return TRUE;
 
869
}
 
870
 
 
871
static gboolean
 
872
gst_decklink_src_video_src_activatepull (GstPad * pad, gboolean active)
 
873
{
 
874
  GstDecklinkSrc *decklinksrc;
 
875
 
 
876
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
877
 
 
878
  GST_DEBUG_OBJECT (decklinksrc, "activatepull");
 
879
 
 
880
 
 
881
  gst_object_unref (decklinksrc);
 
882
  return TRUE;
 
883
}
 
884
 
 
885
static GstPadLinkReturn
 
886
gst_decklink_src_video_src_link (GstPad * pad, GstPad * peer)
 
887
{
 
888
  GstDecklinkSrc *decklinksrc;
 
889
 
 
890
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
891
 
 
892
  GST_DEBUG_OBJECT (decklinksrc, "link");
 
893
 
 
894
 
 
895
  gst_object_unref (decklinksrc);
 
896
  return GST_PAD_LINK_OK;
 
897
}
 
898
 
 
899
static GstFlowReturn
 
900
gst_decklink_src_video_src_getrange (GstPad * pad, guint64 offset, guint length,
 
901
    GstBuffer ** buffer)
 
902
{
 
903
  GstDecklinkSrc *decklinksrc;
 
904
 
 
905
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
906
 
 
907
  GST_DEBUG_OBJECT (decklinksrc, "getrange");
 
908
 
 
909
 
 
910
  gst_object_unref (decklinksrc);
 
911
  return GST_FLOW_OK;
 
912
}
 
913
 
 
914
static gboolean
 
915
gst_decklink_src_video_src_event (GstPad * pad, GstEvent * event)
 
916
{
 
917
  gboolean res;
 
918
  GstDecklinkSrc *decklinksrc;
 
919
 
 
920
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
921
 
 
922
  GST_DEBUG_OBJECT (decklinksrc, "event");
 
923
 
 
924
  switch (GST_EVENT_TYPE (event)) {
 
925
    default:
 
926
      res = gst_pad_event_default (pad, event);
 
927
      break;
 
928
  }
 
929
 
 
930
  gst_object_unref (decklinksrc);
 
931
  return res;
 
932
}
 
933
 
 
934
static gboolean
 
935
gst_decklink_src_video_src_query (GstPad * pad, GstQuery * query)
 
936
{
 
937
  gboolean res;
 
938
  GstDecklinkSrc *decklinksrc;
 
939
 
 
940
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
941
 
 
942
  GST_DEBUG_OBJECT (decklinksrc, "query");
 
943
 
 
944
  switch (GST_QUERY_TYPE (query)) {
 
945
    default:
 
946
      res = gst_pad_query_default (pad, query);
 
947
      break;
 
948
  }
 
949
 
 
950
  gst_object_unref (decklinksrc);
 
951
  return res;
 
952
}
 
953
 
 
954
static GstIterator *
 
955
gst_decklink_src_video_src_iterintlink (GstPad * pad)
 
956
{
 
957
  GstDecklinkSrc *decklinksrc;
 
958
  GstIterator *iter;
 
959
 
 
960
  decklinksrc = GST_DECKLINK_SRC (gst_pad_get_parent (pad));
 
961
 
 
962
  GST_DEBUG_OBJECT (decklinksrc, "iterintlink");
 
963
 
 
964
  iter = gst_pad_iterate_internal_links_default (pad);
 
965
 
 
966
  gst_object_unref (decklinksrc);
 
967
  return iter;
 
968
}
 
969
 
 
970
 
 
971
static void
 
972
video_frame_free (void *data)
 
973
{
 
974
  IDeckLinkVideoInputFrame *video_frame = (IDeckLinkVideoInputFrame *)data;
 
975
 
 
976
  video_frame->Release ();
 
977
}
 
978
 
 
979
static void
 
980
gst_decklink_src_task (void *priv)
 
981
{
 
982
  GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
 
983
  GstBuffer *buffer;
 
984
  GstBuffer *audio_buffer;
 
985
  IDeckLinkVideoInputFrame *video_frame;
 
986
  IDeckLinkAudioInputPacket *audio_frame;
 
987
  int dropped_frames;
 
988
  void *data;
 
989
  int n_samples;
 
990
  GstFlowReturn ret;
 
991
 
 
992
  GST_DEBUG_OBJECT (decklinksrc, "task");
 
993
 
 
994
  g_mutex_lock (decklinksrc->mutex);
 
995
  while (decklinksrc->video_frame == NULL && !decklinksrc->stop) {
 
996
    g_cond_wait (decklinksrc->cond, decklinksrc->mutex);
 
997
  }
 
998
  video_frame = decklinksrc->video_frame;
 
999
  audio_frame = decklinksrc->audio_frame;
 
1000
  dropped_frames = decklinksrc->dropped_frames;
 
1001
  decklinksrc->video_frame = NULL;
 
1002
  decklinksrc->audio_frame = NULL;
 
1003
  g_mutex_unlock (decklinksrc->mutex);
 
1004
 
 
1005
  if (decklinksrc->stop) {
 
1006
    GST_ERROR("stopping task");
 
1007
    return;
 
1008
  }
 
1009
 
 
1010
  if (dropped_frames > 0) {
 
1011
    GST_ELEMENT_ERROR(decklinksrc, RESOURCE, READ, (NULL), (NULL));
 
1012
    /* ERROR */
 
1013
    return;
 
1014
  }
 
1015
 
 
1016
  video_frame->GetBytes (&data);
 
1017
  if (decklinksrc->copy_data) {
 
1018
    buffer = gst_buffer_new_and_alloc (decklinksrc->width * decklinksrc->height * 2);
 
1019
 
 
1020
    memcpy (GST_BUFFER_DATA (buffer), data, decklinksrc->width * decklinksrc->height * 2);
 
1021
 
 
1022
    video_frame->Release ();
 
1023
  } else {
 
1024
    buffer = gst_buffer_new ();
 
1025
    GST_BUFFER_SIZE (buffer) = decklinksrc->width * decklinksrc->height * 2;
 
1026
 
 
1027
    GST_BUFFER_DATA (buffer) = (guint8 *)data;
 
1028
 
 
1029
    GST_BUFFER_FREE_FUNC (buffer) = video_frame_free;
 
1030
    GST_BUFFER_MALLOCDATA (buffer) = (guint8 *)video_frame;
 
1031
  }
 
1032
 
 
1033
  GST_BUFFER_TIMESTAMP (buffer) =
 
1034
    gst_util_uint64_scale_int (decklinksrc->num_frames * GST_SECOND,
 
1035
        decklinksrc->fps_d, decklinksrc->fps_n);
 
1036
  GST_BUFFER_DURATION (buffer) =
 
1037
    gst_util_uint64_scale_int ((decklinksrc->num_frames + 1) * GST_SECOND,
 
1038
        decklinksrc->fps_d, decklinksrc->fps_n) -
 
1039
    GST_BUFFER_TIMESTAMP (buffer);
 
1040
  GST_BUFFER_OFFSET (buffer) = decklinksrc->num_frames;
 
1041
  if (decklinksrc->num_frames == 0) {
 
1042
    GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DISCONT);
 
1043
  }
 
1044
  decklinksrc->num_frames ++;
 
1045
 
 
1046
  if (decklinksrc->video_caps == NULL) {
 
1047
    decklinksrc->video_caps = gst_caps_new_simple ("video/x-raw-yuv",
 
1048
        "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('U','Y','V','Y'),
 
1049
        "width", G_TYPE_INT, decklinksrc->width,
 
1050
        "height", G_TYPE_INT, decklinksrc->height,
 
1051
        "framerate", GST_TYPE_FRACTION,
 
1052
        decklinksrc->fps_n, decklinksrc->fps_d,
 
1053
        "interlaced", G_TYPE_BOOLEAN, decklinksrc->interlaced,
 
1054
        NULL);
 
1055
  }
 
1056
  gst_buffer_set_caps (buffer, decklinksrc->video_caps);
 
1057
 
 
1058
  ret = gst_pad_push (decklinksrc->videosrcpad, buffer);
 
1059
  if (ret != GST_FLOW_OK) {
 
1060
    GST_ELEMENT_ERROR(decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
 
1061
  }
 
1062
 
 
1063
 
 
1064
  n_samples = audio_frame->GetSampleFrameCount();
 
1065
  audio_frame->GetBytes (&data);
 
1066
  audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
 
1067
  memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2);
 
1068
  audio_frame->Release ();
 
1069
 
 
1070
  GST_BUFFER_TIMESTAMP (audio_buffer) =
 
1071
    gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
 
1072
        1, 48000);
 
1073
  GST_BUFFER_DURATION (audio_buffer) =
 
1074
    gst_util_uint64_scale_int ((decklinksrc->num_audio_samples + n_samples) * GST_SECOND,
 
1075
        1, 48000) - GST_BUFFER_TIMESTAMP (audio_buffer);
 
1076
  decklinksrc->num_audio_samples += n_samples;
 
1077
 
 
1078
  if (decklinksrc->audio_caps == NULL) {
 
1079
    decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
 
1080
        "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
 
1081
        "signed", G_TYPE_BOOLEAN, TRUE,
 
1082
        "depth", G_TYPE_INT, 16,
 
1083
        "width", G_TYPE_INT, 16,
 
1084
        "channels", G_TYPE_INT, 2,
 
1085
        "rate", G_TYPE_INT, 48000,
 
1086
        NULL);
 
1087
  }
 
1088
  gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps);
 
1089
 
 
1090
  ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer);
 
1091
  if (ret != GST_FLOW_OK) {
 
1092
    GST_ELEMENT_ERROR(decklinksrc, CORE, NEGOTIATION, (NULL), (NULL));
 
1093
  }
 
1094
}
 
1095
 
 
1096