diff --git a/sys/decklink/capture.cpp b/sys/decklink/capture.cpp index 99bbbb3d12..83567e9849 100644 --- a/sys/decklink/capture.cpp +++ b/sys/decklink/capture.cpp @@ -57,8 +57,7 @@ DeckLinkCaptureDelegate::~DeckLinkCaptureDelegate () pthread_mutex_destroy (&m_mutex); } -ULONG -DeckLinkCaptureDelegate::AddRef (void) +ULONG DeckLinkCaptureDelegate::AddRef (void) { pthread_mutex_lock (&m_mutex); m_refCount++; @@ -67,15 +66,15 @@ DeckLinkCaptureDelegate::AddRef (void) return (ULONG) m_refCount; } -ULONG -DeckLinkCaptureDelegate::Release (void) +ULONG DeckLinkCaptureDelegate::Release (void) { pthread_mutex_lock (&m_mutex); m_refCount--; pthread_mutex_unlock (&m_mutex); if (m_refCount == 0) { - delete this; + delete + this; return 0; } @@ -86,7 +85,12 @@ HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived (IDeckLinkVideoInputFrame * videoFrame, IDeckLinkAudioInputPacket * audioFrame) { - GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv); + GstDecklinkSrc *decklinksrc; + + g_return_val_if_fail (priv != NULL, S_OK); + g_return_val_if_fail (GST_IS_DECKLINK_SRC (priv), S_OK); + + decklinksrc = GST_DECKLINK_SRC (priv); // Handle Video Frame if (videoFrame) { @@ -133,4 +137,3 @@ HRESULT GST_ERROR ("moo"); return S_OK; } - diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp index 4d4ed445ae..122bc70b2d 100644 --- a/sys/decklink/gstdecklink.cpp +++ b/sys/decklink/gstdecklink.cpp @@ -22,9 +22,72 @@ #endif #include +#include "gstdecklink.h" #include "gstdecklinksrc.h" #include "gstdecklinksink.h" +GType +gst_decklink_mode_get_type (void) +{ + static GType type; + + if (!type) { + static const GEnumValue modes[] = { + {GST_DECKLINK_MODE_NTSC, "ntsc", "NTSC SD 60i"}, + {GST_DECKLINK_MODE_PAL, "pal", "PAL SD 50i"}, + {GST_DECKLINK_MODE_1080i50, "1080i50", "HD1080 50i"}, + {GST_DECKLINK_MODE_1080i60, "1080i60", "HD1080 60i"}, + {GST_DECKLINK_MODE_720p50, "720p50", "HD720 50p"}, + {GST_DECKLINK_MODE_720p60, "720p60", "HD720 60p"}, + {0, NULL, NULL} + }; + + type = g_enum_register_static ("GstDecklinkModes", modes); + } + return type; +} + +static const GstDecklinkMode modes[] = { + {bmdModeNTSC, 720, 486, 30000, 1001, true}, + {bmdModePAL, 720, 576, 25, 1, true}, + {bmdModeHD1080i50, 1920, 1080, 25, 1, true}, + {bmdModeHD1080i5994, 1920, 1080, 30000, 1001, true}, + {bmdModeHD720p50, 1280, 720, 50, 1, true}, + {bmdModeHD720p5994, 1280, 720, 60000, 1001, true} +}; + +#if 0 + //{ bmdModeNTSC2398, 720,486,24000,1001,true }, + //{ bmdModeHD1080p2398, 1920,1080,24000,1001,false }, + //{ bmdModeHD1080p24, 1920,1080,24,1,false }, + //{ bmdModeHD1080p25, 1920,1080,25,1,false }, + //{ bmdModeHD1080p2997, 1920,1080,30000,1001,false }, + //{ bmdModeHD1080p30, 1920,1080,30,1,false }, + //{ bmdModeHD1080i6000, 1920,1080,30,1,true }, + //{ bmdModeHD720p60, 1280,720,60,1,true } +#endif + +const GstDecklinkMode * +gst_decklink_get_mode (GstDecklinkModeEnum e) +{ + return &modes[e]; +} + +GstCaps * +gst_decklink_mode_get_caps (GstDecklinkModeEnum e) +{ + const GstDecklinkMode *mode = &modes[e]; + + return gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), + "width", G_TYPE_INT, mode->width, + "height", G_TYPE_INT, mode->height, + "framerate", GST_TYPE_FRACTION, + mode->fps_n, mode->fps_d, + "interlaced", G_TYPE_BOOLEAN, mode->interlaced, NULL); +} + + static gboolean plugin_init (GstPlugin * plugin) { diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h new file mode 100644 index 0000000000..ab5b5647a9 --- /dev/null +++ b/sys/decklink/gstdecklink.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_DECKLINK_H_ +#define _GST_DECKLINK_H_ + +#include +#include "DeckLinkAPI.h" + + +typedef enum { + GST_DECKLINK_MODE_NTSC, + GST_DECKLINK_MODE_PAL, + GST_DECKLINK_MODE_1080i50, + GST_DECKLINK_MODE_1080i60, + GST_DECKLINK_MODE_720p50, + GST_DECKLINK_MODE_720p60 +} GstDecklinkModeEnum; +#define GST_TYPE_DECKLINK_MODE (gst_decklink_mode_get_type ()) +GType gst_decklink_mode_get_type (void); + + +typedef struct _GstDecklinkMode GstDecklinkMode; +struct _GstDecklinkMode { + BMDDisplayMode mode; + int width; + int height; + int fps_n; + int fps_d; + gboolean interlaced; +}; + +const GstDecklinkMode * gst_decklink_get_mode (GstDecklinkModeEnum e); +GstCaps * gst_decklink_mode_get_caps (GstDecklinkModeEnum e); + +#define GST_DECKLINK_MODE_CAPS(w,h,n,d,i) \ + "video/x-raw-yuv,format=(fourcc)UYVY,width=" #w ",height=" #h \ + ",framerate=" #n "/" #d ",interlaced=" #i + +#define GST_DECKLINK_CAPS \ + GST_DECKLINK_MODE_CAPS(720,486,30000,1001,true) ";" \ + GST_DECKLINK_MODE_CAPS(720,576,25,1,true) ";" \ + GST_DECKLINK_MODE_CAPS(1920,1080,25,1,true) ";" \ + GST_DECKLINK_MODE_CAPS(1920,1080,30000,1001,true) ";" \ + GST_DECKLINK_MODE_CAPS(1280,720,50,1,true) ";" \ + GST_DECKLINK_MODE_CAPS(1280,720,60000,1001,true) + +#if 0 + MODE(720,486,24000,1001,true) ";" \ + MODE(1920,1080,24000,1001,false) ";" \ + MODE(1920,1080,24,1,false) ";" \ + MODE(1920,1080,25,1,false) ";" \ + MODE(1920,1080,30000,1001,false) ";" \ + MODE(1920,1080,30,1,false) ";" \ + MODE(1920,1080,30,1,true) ";" \ + MODE(1280,720,60,1,true) +#endif + + +#endif diff --git a/sys/decklink/gstdecklinksink.cpp b/sys/decklink/gstdecklinksink.cpp index 5f84ddf459..868dd3f978 100644 --- a/sys/decklink/gstdecklinksink.cpp +++ b/sys/decklink/gstdecklinksink.cpp @@ -36,6 +36,7 @@ #include #include +#include "gstdecklink.h" #include "gstdecklinksink.h" #include @@ -118,82 +119,25 @@ static GstIterator *gst_decklink_sink_audiosink_iterintlink (GstPad * pad); enum { - PROP_0 + PROP_0, + PROP_MODE }; /* pad templates */ -#define MODE(w,h,n,d,i) \ - "video/x-raw-yuv,format=(fourcc)UYVY,width=" #w ",height=" #h \ - ",framerate=" #n "/" #d ",interlaced=" #i - static GstStaticPadTemplate gst_decklink_sink_videosink_template = GST_STATIC_PAD_TEMPLATE ("videosink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (MODE (720, 486, 30000, 1001, true) - )); -#if 0 -MODE (720, 486, 24000, 1001, true) ";" -MODE (720, 576, 25, 1, true) - ";" -MODE (1920, 1080, 24000, 1001, false) - ";" -MODE (1920, 1080, 24, 1, false) - ";" -MODE (1920, 1080, 25, 1, false) - ";" -MODE (1920, 1080, 30000, 1001, false) - ";" -MODE (1920, 1080, 30, 1, false) - ";" -MODE (1920, 1080, 25, 1, true) - ";" -MODE (1920, 1080, 30000, 1001, true) - ";" -MODE (1920, 1080, 30, 1, true) - ";" -MODE (1280, 720, 50, 1, true) - ";" -MODE (1280, 720, 60000, 1001, true) - ";" -MODE (1280, 720, 60, 1, true) -#endif - static GstStaticPadTemplate gst_decklink_sink_audiosink_template = - GST_STATIC_PAD_TEMPLATE ("audiosink", + GST_STATIC_CAPS (GST_DECKLINK_CAPS)); + +static GstStaticPadTemplate gst_decklink_sink_audiosink_template = +GST_STATIC_PAD_TEMPLATE ("audiosink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("audio/x-raw-int,width=16,depth=16,channels=2,rate=48000") ); - typedef struct _DecklinkMode DecklinkMode; - struct _DecklinkMode - { - BMDDisplayMode mode; - int width; - int height; - int fps_n; - int fps_d; - gboolean interlaced; - }; - - static DecklinkMode modes[] = { - {bmdModeNTSC, 720, 486, 30000, 1001, true}, - {bmdModeNTSC2398, 720, 486, 24000, 1001, true}, - {bmdModePAL, 720, 576, 25, 1, true}, - {bmdModeHD1080p2398, 1920, 1080, 24000, 1001, false}, - {bmdModeHD1080p24, 1920, 1080, 24, 1, false}, - {bmdModeHD1080p25, 1920, 1080, 25, 1, false}, - {bmdModeHD1080p2997, 1920, 1080, 30000, 1001, false}, - {bmdModeHD1080p30, 1920, 1080, 30, 1, false}, - {bmdModeHD1080i50, 1920, 1080, 25, 1, true}, - {bmdModeHD1080i5994, 1920, 1080, 30000, 1001, true}, - {bmdModeHD1080i6000, 1920, 1080, 30, 1, true}, - {bmdModeHD720p50, 1280, 720, 50, 1, true}, - {bmdModeHD720p5994, 1280, 720, 60000, 1001, true}, - {bmdModeHD720p60, 1280, 720, 60, 1, true} - }; - /* class initialization */ @@ -238,6 +182,12 @@ gst_decklink_sink_class_init (GstDecklinkSinkClass * klass) element_class->send_event = GST_DEBUG_FUNCPTR (gst_decklink_sink_send_event); element_class->query = GST_DEBUG_FUNCPTR (gst_decklink_sink_query); + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", "Mode", + GST_TYPE_DECKLINK_MODE, GST_DECKLINK_MODE_NTSC, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + G_PARAM_CONSTRUCT))); + } static void @@ -313,14 +263,7 @@ gst_decklink_sink_init (GstDecklinkSink * decklinksink, decklinksink->cond = g_cond_new (); decklinksink->mutex = g_mutex_new (); - decklinksink->mode = 0; - - decklinksink->width = modes[decklinksink->mode].width; - decklinksink->height = modes[decklinksink->mode].height; - decklinksink->fps_n = modes[decklinksink->mode].fps_n; - decklinksink->fps_d = modes[decklinksink->mode].fps_d; - decklinksink->interlaced = modes[decklinksink->mode].interlaced; - decklinksink->bmd_mode = modes[decklinksink->mode].mode; + decklinksink->mode = GST_DECKLINK_MODE_NTSC; decklinksink->callback = new Output; decklinksink->callback->decklinksink = decklinksink; @@ -330,9 +273,15 @@ void gst_decklink_sink_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { + GstDecklinkSink *decklinksink; + g_return_if_fail (GST_IS_DECKLINK_SINK (object)); + decklinksink = GST_DECKLINK_SINK (object); switch (property_id) { + case PROP_MODE: + decklinksink->mode = (GstDecklinkModeEnum) g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -343,9 +292,15 @@ void gst_decklink_sink_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { + GstDecklinkSink *decklinksink; + g_return_if_fail (GST_IS_DECKLINK_SINK (object)); + decklinksink = GST_DECKLINK_SINK (object); switch (property_id) { + case PROP_MODE: + g_value_set_enum (value, decklinksink->mode); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -384,10 +339,7 @@ gst_decklink_sink_start (GstDecklinkSink * decklinksink) { IDeckLinkIterator *iterator; HRESULT ret; - IDeckLinkDisplayModeIterator *mode_iterator; - IDeckLinkDisplayMode *mode; - BMDTimeValue fps_n; - BMDTimeScale fps_d; + const GstDecklinkMode *mode; iterator = CreateDeckLinkIteratorInstance (); if (iterator == NULL) { @@ -410,29 +362,9 @@ gst_decklink_sink_start (GstDecklinkSink * decklinksink) decklinksink->output->SetAudioCallback (decklinksink->callback); - ret = decklinksink->output->GetDisplayModeIterator (&mode_iterator); - if (ret != S_OK) { - GST_ERROR ("failed to get display mode iterator"); - return FALSE; - } + mode = gst_decklink_get_mode (decklinksink->mode); - while (mode_iterator->Next (&mode) == S_OK) { - break; - } - if (!mode) { - GST_ERROR ("bad mode"); - return FALSE; - } - - decklinksink->width = mode->GetWidth (); - decklinksink->height = mode->GetHeight (); - mode->GetFrameRate (&fps_n, &fps_d); - decklinksink->fps_n = fps_n; - decklinksink->fps_d = fps_d; - - decklinksink->display_mode = mode->GetDisplayMode (); - - ret = decklinksink->output->EnableVideoOutput (decklinksink->display_mode, + ret = decklinksink->output->EnableVideoOutput (mode->mode, bmdVideoOutputFlagDefault); if (ret != S_OK) { GST_ERROR ("failed to enable video output"); @@ -440,8 +372,8 @@ gst_decklink_sink_start (GstDecklinkSink * decklinksink) } //decklinksink->video_enabled = TRUE; - decklinksink->output-> - SetScheduledFrameCompletionCallback (decklinksink->callback); + decklinksink->output->SetScheduledFrameCompletionCallback (decklinksink-> + callback); if (0) { ret = decklinksink->output->EnableAudioOutput (bmdAudioSampleRate48kHz, @@ -573,7 +505,7 @@ gst_decklink_sink_videosink_getcaps (GstPad * pad) GST_DEBUG_OBJECT (decklinksink, "getcaps"); - caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + caps = gst_decklink_mode_get_caps (decklinksink->mode); gst_object_unref (decklinksink); return caps; @@ -678,6 +610,7 @@ gst_decklink_sink_videosink_chain (GstPad * pad, GstBuffer * buffer) IDeckLinkMutableVideoFrame *frame; void *data; GstFlowReturn ret; + const GstDecklinkMode *mode; decklinksink = GST_DECKLINK_SINK (gst_pad_get_parent (pad)); @@ -696,8 +629,10 @@ gst_decklink_sink_videosink_chain (GstPad * pad, GstBuffer * buffer) } #endif - decklinksink->output->CreateVideoFrame (decklinksink->width, - decklinksink->height, decklinksink->width * 2, bmdFormat8BitYUV, + mode = gst_decklink_get_mode (decklinksink->mode); + + decklinksink->output->CreateVideoFrame (mode->width, + mode->height, mode->width * 2, bmdFormat8BitYUV, bmdFrameFlagDefault, &frame); frame->GetBytes (&data); @@ -715,8 +650,7 @@ gst_decklink_sink_videosink_chain (GstPad * pad, GstBuffer * buffer) if (!decklinksink->stop) { decklinksink->output->ScheduleVideoFrame (frame, - decklinksink->num_frames * decklinksink->fps_n, - decklinksink->fps_n, decklinksink->fps_d); + decklinksink->num_frames * mode->fps_d, mode->fps_d, mode->fps_n); decklinksink->num_frames++; if (!decklinksink->sched_started) { @@ -1050,15 +984,13 @@ HRESULT return S_OK; } -HRESULT -Output::ScheduledPlaybackHasStopped () +HRESULT Output::ScheduledPlaybackHasStopped () { GST_ERROR ("ScheduledPlaybackHasStopped"); return S_OK; } -HRESULT -Output::RenderAudioSamples (bool preroll) +HRESULT Output::RenderAudioSamples (bool preroll) { GST_ERROR ("RenderAudioSamples"); diff --git a/sys/decklink/gstdecklinksink.h b/sys/decklink/gstdecklinksink.h index 2f0d1d799b..e5b7765874 100644 --- a/sys/decklink/gstdecklinksink.h +++ b/sys/decklink/gstdecklinksink.h @@ -21,6 +21,7 @@ #define _GST_DECKLINK_SINK_H_ #include +#include "gstdecklink.h" #include "DeckLinkAPI.h" G_BEGIN_DECLS @@ -68,15 +69,9 @@ struct _GstDecklinkSink gboolean sched_started; int num_frames; - int fps_n; - int fps_d; - int width; - int height; - gboolean interlaced; - BMDDisplayMode bmd_mode; /* properties */ - int mode; + GstDecklinkModeEnum mode; }; diff --git a/sys/decklink/gstdecklinksrc.cpp b/sys/decklink/gstdecklinksrc.cpp index f2959aeca2..f5a22f15e2 100644 --- a/sys/decklink/gstdecklinksrc.cpp +++ b/sys/decklink/gstdecklinksrc.cpp @@ -36,6 +36,7 @@ #endif #include +#include "gstdecklink.h" #include "gstdecklinksrc.h" #include "capture.h" #include @@ -116,7 +117,9 @@ static void gst_decklink_src_task (void *priv); enum { - PROP_0 + PROP_0, + PROP_MODE, + PROP_OPTICAL }; /* pad templates */ @@ -128,57 +131,11 @@ GST_STATIC_PAD_TEMPLATE ("audiosrc", GST_STATIC_CAPS ("audio/x-raw-int,width=16,depth=16,channels=2,rate=48000") ); -#define MODE(w,h,n,d,i) \ - "video/x-raw-yuv,format=(fourcc)UYVY,width=" #w ",height=" #h \ - ",framerate=" #n "/" #d ",interlaced=" #i - static GstStaticPadTemplate gst_decklink_src_video_src_template = - GST_STATIC_PAD_TEMPLATE ("videosrc", +GST_STATIC_PAD_TEMPLATE ("videosrc", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (MODE (720, 486, 30000, 1001, true) ";" - MODE (720, 486, 24000, 1001, true) ";" - MODE (720, 576, 25, 1, true) ";" - MODE (1920, 1080, 24000, 1001, false) ";" - MODE (1920, 1080, 24, 1, false) ";" - MODE (1920, 1080, 25, 1, false) ";" - MODE (1920, 1080, 30000, 1001, false) ";" - MODE (1920, 1080, 30, 1, false) ";" - MODE (1920, 1080, 25, 1, true) ";" - MODE (1920, 1080, 30000, 1001, true) ";" - MODE (1920, 1080, 30, 1, true) ";" - MODE (1280, 720, 50, 1, true) ";" - MODE (1280, 720, 60000, 1001, true) ";" MODE (1280, 720, 60, 1, true) - )); - -typedef struct _DecklinkMode DecklinkMode; -struct _DecklinkMode -{ - BMDDisplayMode mode; - int width; - int height; - int fps_n; - int fps_d; - gboolean interlaced; -}; - -static DecklinkMode modes[] = { - {bmdModeNTSC, 720, 486, 30000, 1001, true}, - {bmdModeNTSC2398, 720, 486, 24000, 1001, true}, - {bmdModePAL, 720, 576, 25, 1, true}, - {bmdModeHD1080p2398, 1920, 1080, 24000, 1001, false}, - {bmdModeHD1080p24, 1920, 1080, 24, 1, false}, - {bmdModeHD1080p25, 1920, 1080, 25, 1, false}, - {bmdModeHD1080p2997, 1920, 1080, 30000, 1001, false}, - {bmdModeHD1080p30, 1920, 1080, 30, 1, false}, - {bmdModeHD1080i50, 1920, 1080, 25, 1, true}, - {bmdModeHD1080i5994, 1920, 1080, 30000, 1001, true}, - {bmdModeHD1080i6000, 1920, 1080, 30, 1, true}, - {bmdModeHD720p50, 1280, 720, 50, 1, true}, - {bmdModeHD720p5994, 1280, 720, 60000, 1001, true}, - {bmdModeHD720p60, 1280, 720, 60, 1, true} -}; - + GST_STATIC_CAPS (GST_DECKLINK_CAPS)); /* class initialization */ @@ -226,6 +183,17 @@ gst_decklink_src_class_init (GstDecklinkSrcClass * klass) element_class->send_event = GST_DEBUG_FUNCPTR (gst_decklink_src_send_event); element_class->query = GST_DEBUG_FUNCPTR (gst_decklink_src_query); + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", "Mode", + GST_TYPE_DECKLINK_MODE, GST_DECKLINK_MODE_NTSC, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + G_PARAM_CONSTRUCT))); + + g_object_class_install_property (gobject_class, PROP_OPTICAL, + g_param_spec_boolean ("optical", "Optical", "Optical", + TRUE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + G_PARAM_CONSTRUCT))); } static void @@ -301,14 +269,7 @@ gst_decklink_src_init (GstDecklinkSrc * decklinksrc, decklinksrc->mutex = g_mutex_new (); decklinksrc->copy_data = TRUE; - decklinksrc->mode = 0; - - decklinksrc->width = modes[decklinksrc->mode].width; - decklinksrc->height = modes[decklinksrc->mode].height; - decklinksrc->fps_n = modes[decklinksrc->mode].fps_n; - decklinksrc->fps_d = modes[decklinksrc->mode].fps_d; - decklinksrc->interlaced = modes[decklinksrc->mode].interlaced; - decklinksrc->bmd_mode = modes[decklinksrc->mode].mode; + decklinksrc->mode = GST_DECKLINK_MODE_NTSC; } @@ -316,9 +277,18 @@ void gst_decklink_src_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { + GstDecklinkSrc *decklinksrc; + g_return_if_fail (GST_IS_DECKLINK_SRC (object)); + decklinksrc = GST_DECKLINK_SRC (object); switch (property_id) { + case PROP_MODE: + decklinksrc->mode = (GstDecklinkModeEnum) g_value_get_enum (value); + break; + case PROP_OPTICAL: + decklinksrc->optical = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -329,9 +299,18 @@ void gst_decklink_src_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { + GstDecklinkSrc *decklinksrc; + g_return_if_fail (GST_IS_DECKLINK_SRC (object)); + decklinksrc = GST_DECKLINK_SRC (object); switch (property_id) { + case PROP_MODE: + g_value_set_enum (value, decklinksrc->mode); + break; + case PROP_OPTICAL: + g_value_set_boolean (value, decklinksrc->optical); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -394,15 +373,13 @@ gst_decklink_src_start (GstElement * element) GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element); IDeckLinkIterator *iterator; DeckLinkCaptureDelegate *delegate; - IDeckLinkDisplayModeIterator *mode_iterator; - IDeckLinkDisplayMode *mode; - int i; + //IDeckLinkDisplayModeIterator *mode_iterator; + //IDeckLinkDisplayMode *mode; int sample_depth; int channels; - BMDVideoInputFlags input_flags; - BMDDisplayMode selected_mode; - BMDPixelFormat pixel_format; HRESULT ret; + const GstDecklinkMode *mode; + IDeckLinkConfiguration *config; GST_DEBUG_OBJECT (decklinksrc, "start"); @@ -429,6 +406,21 @@ gst_decklink_src_start (GstElement * element) delegate->priv = decklinksrc; decklinksrc->input->SetCallback (delegate); + ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkConfiguration, + (void **) &config); + if (ret != S_OK) { + GST_ERROR ("query interface failed"); + return FALSE; + } + + ret = config->SetInt (bmdDeckLinkConfigVideoInputConnection, + decklinksrc->optical ? bmdVideoConnectionOpticalSDI : + bmdVideoConnectionSDI); + if (ret != S_OK) { + GST_ERROR ("set configuration (input source)"); + return FALSE; + } +#if 0 ret = decklinksrc->input->GetDisplayModeIterator (&mode_iterator); if (ret != S_OK) { GST_ERROR ("failed to get display mode iterator"); @@ -441,17 +433,16 @@ gst_decklink_src_start (GstElement * element) mode->GetName (&mode_name); - GST_ERROR ("%d: mode name: %s", i, mode_name); + GST_DEBUG ("%d: mode name: %s", i, mode_name); mode->Release (); i++; } +#endif - pixel_format = bmdFormat8BitYUV; - selected_mode = decklinksrc->bmd_mode; - input_flags = 0; - ret = decklinksrc->input->EnableVideoInput (selected_mode, pixel_format, - input_flags); + mode = gst_decklink_get_mode (decklinksrc->mode); + + ret = decklinksrc->input->EnableVideoInput (mode->mode, bmdFormat8BitYUV, 0); if (ret != S_OK) { GST_ERROR ("enable video input failed"); return FALSE; @@ -459,8 +450,7 @@ gst_decklink_src_start (GstElement * element) sample_depth = 16; channels = 2; - ret = - decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz, + ret = decklinksrc->input->EnableAudioInput (bmdAudioSampleRate48kHz, sample_depth, channels); if (ret != S_OK) { GST_ERROR ("enable video input failed"); @@ -494,6 +484,13 @@ gst_decklink_src_stop (GstElement * element) gst_task_join (decklinksrc->task); + decklinksrc->input->StopStreams (); + decklinksrc->input->DisableVideoInput (); + decklinksrc->input->DisableAudioInput (); + + decklinksrc->input->Release (); + decklinksrc->input = NULL; + return TRUE; } @@ -788,7 +785,7 @@ gst_decklink_src_video_src_getcaps (GstPad * pad) GST_DEBUG_OBJECT (decklinksrc, "getcaps"); - caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + caps = gst_decklink_mode_get_caps (decklinksrc->mode); gst_object_unref (decklinksrc); return caps; @@ -991,6 +988,7 @@ gst_decklink_src_task (void *priv) void *data; int n_samples; GstFlowReturn ret; + const GstDecklinkMode *mode; GST_DEBUG_OBJECT (decklinksrc, "task"); @@ -1006,7 +1004,7 @@ gst_decklink_src_task (void *priv) g_mutex_unlock (decklinksrc->mutex); if (decklinksrc->stop) { - GST_ERROR ("stopping task"); + GST_DEBUG ("stopping task"); return; } @@ -1016,18 +1014,18 @@ gst_decklink_src_task (void *priv) return; } + mode = gst_decklink_get_mode (decklinksrc->mode); + video_frame->GetBytes (&data); if (decklinksrc->copy_data) { - buffer = - gst_buffer_new_and_alloc (decklinksrc->width * decklinksrc->height * 2); + buffer = gst_buffer_new_and_alloc (mode->width * mode->height * 2); - memcpy (GST_BUFFER_DATA (buffer), data, - decklinksrc->width * decklinksrc->height * 2); + memcpy (GST_BUFFER_DATA (buffer), data, mode->width * mode->height * 2); video_frame->Release (); } else { buffer = gst_buffer_new (); - GST_BUFFER_SIZE (buffer) = decklinksrc->width * decklinksrc->height * 2; + GST_BUFFER_SIZE (buffer) = mode->width * mode->height * 2; GST_BUFFER_DATA (buffer) = (guint8 *) data; @@ -1037,10 +1035,10 @@ gst_decklink_src_task (void *priv) GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale_int (decklinksrc->num_frames * GST_SECOND, - decklinksrc->fps_d, decklinksrc->fps_n); + mode->fps_d, mode->fps_n); GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int ((decklinksrc->num_frames + 1) * GST_SECOND, - decklinksrc->fps_d, decklinksrc->fps_n) - GST_BUFFER_TIMESTAMP (buffer); + mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer); GST_BUFFER_OFFSET (buffer) = decklinksrc->num_frames; if (decklinksrc->num_frames == 0) { GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); @@ -1048,13 +1046,7 @@ gst_decklink_src_task (void *priv) decklinksrc->num_frames++; if (decklinksrc->video_caps == NULL) { - decklinksrc->video_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), - "width", G_TYPE_INT, decklinksrc->width, - "height", G_TYPE_INT, decklinksrc->height, - "framerate", GST_TYPE_FRACTION, - decklinksrc->fps_n, decklinksrc->fps_d, - "interlaced", G_TYPE_BOOLEAN, decklinksrc->interlaced, NULL); + decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode); } gst_buffer_set_caps (buffer, decklinksrc->video_caps); @@ -1063,34 +1055,35 @@ gst_decklink_src_task (void *priv) GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL)); } + if (gst_pad_is_linked (decklinksrc->audiosrcpad)) { + n_samples = audio_frame->GetSampleFrameCount (); + audio_frame->GetBytes (&data); + audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2); + memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2); - n_samples = audio_frame->GetSampleFrameCount (); - audio_frame->GetBytes (&data); - audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2); - memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2); + GST_BUFFER_TIMESTAMP (audio_buffer) = + gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND, + 1, 48000); + GST_BUFFER_DURATION (audio_buffer) = + gst_util_uint64_scale_int ((decklinksrc->num_audio_samples + + n_samples) * GST_SECOND, 1, + 48000) - GST_BUFFER_TIMESTAMP (audio_buffer); + decklinksrc->num_audio_samples += n_samples; + + if (decklinksrc->audio_caps == NULL) { + decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, LITTLE_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, + "depth", G_TYPE_INT, 16, + "width", G_TYPE_INT, 16, + "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL); + } + gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps); + + ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer); + if (ret != GST_FLOW_OK) { + GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL)); + } + } audio_frame->Release (); - - GST_BUFFER_TIMESTAMP (audio_buffer) = - gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND, - 1, 48000); - GST_BUFFER_DURATION (audio_buffer) = - gst_util_uint64_scale_int ((decklinksrc->num_audio_samples + - n_samples) * GST_SECOND, 1, - 48000) - GST_BUFFER_TIMESTAMP (audio_buffer); - decklinksrc->num_audio_samples += n_samples; - - if (decklinksrc->audio_caps == NULL) { - decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int", - "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, - "signed", G_TYPE_BOOLEAN, TRUE, - "depth", G_TYPE_INT, 16, - "width", G_TYPE_INT, 16, - "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL); - } - gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps); - - ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (decklinksrc, CORE, NEGOTIATION, (NULL), (NULL)); - } } diff --git a/sys/decklink/gstdecklinksrc.h b/sys/decklink/gstdecklinksrc.h index e191675fc1..11154fd988 100644 --- a/sys/decklink/gstdecklinksrc.h +++ b/sys/decklink/gstdecklinksrc.h @@ -21,6 +21,7 @@ #define _GST_DECKLINK_SRC_H_ #include +#include "gstdecklink.h" #include "DeckLinkAPI.h" G_BEGIN_DECLS @@ -69,7 +70,8 @@ struct _GstDecklinkSrc /* properties */ gboolean copy_data; - int mode; + GstDecklinkModeEnum mode; + gboolean optical; }; struct _GstDecklinkSrcClass