summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2012-09-23 13:15:20 -0700
committerTim-Philipp Müller <tim@centricular.net>2012-09-23 21:27:36 +0100
commit65a1f79bcbaf1089888a7e8bba89e5c2c2b6457e (patch)
tree94eb7d298a18f3a56b174053f0e228d92074107b
parentdd66252f23b198d03671ed2c913623ccd7a518a7 (diff)
downloadgstreamer-plugins-bad-65a1f79bcbaf1089888a7e8bba89e5c2c2b6457e.tar.gz
decklink: change device instance lifecycle
The decklink driver eventually crashes after repeated creation/deletion of device, input, output, and configuration objects. Change to create these at the outset and keep them around forever.
-rw-r--r--sys/decklink/capture.cpp105
-rw-r--r--sys/decklink/gstdecklink.cpp86
-rw-r--r--sys/decklink/gstdecklink.h4
-rw-r--r--sys/decklink/gstdecklinksink.cpp12
-rw-r--r--sys/decklink/gstdecklinksrc.cpp46
-rw-r--r--sys/decklink/gstdecklinksrc.h1
6 files changed, 150 insertions, 104 deletions
diff --git a/sys/decklink/capture.cpp b/sys/decklink/capture.cpp
index 8804eebaf..c2a0bcb3d 100644
--- a/sys/decklink/capture.cpp
+++ b/sys/decklink/capture.cpp
@@ -84,59 +84,80 @@ HRESULT
videoFrame, IDeckLinkAudioInputPacket * audioFrame)
{
GstDecklinkSrc *decklinksrc;
+ const char *timecodeString = NULL;
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) {
- if (videoFrame->GetFlags () & bmdFrameHasNoInputSource) {
- GST_DEBUG ("Frame received - No input signal detected");
- } else {
- const char *timecodeString = NULL;
- if (g_timecodeFormat != 0) {
- IDeckLinkTimecode *timecode;
- if (videoFrame->GetTimecode (g_timecodeFormat, &timecode) == S_OK) {
- timecode->GetString (&timecodeString);
- CONVERT_COM_STRING (timecodeString);
- }
- }
-
- GST_DEBUG ("Frame received [%s] - %s - Size: %li bytes",
- timecodeString != NULL ? timecodeString : "No timecode",
- "Valid Frame", videoFrame->GetRowBytes () * videoFrame->GetHeight ());
-
- if (timecodeString)
- FREE_COM_STRING (timecodeString);
-
- g_mutex_lock (decklinksrc->mutex);
- if (decklinksrc->video_frame != NULL) {
- decklinksrc->dropped_frames++;
- } else {
- videoFrame->AddRef ();
- decklinksrc->video_frame = videoFrame;
- if (audioFrame) {
- audioFrame->AddRef ();
- decklinksrc->audio_frame = audioFrame;
- }
- }
-
- /* increment regardless whether frame was dropped or not */
- decklinksrc->frame_num++;
-
- g_cond_signal (decklinksrc->cond);
- g_mutex_unlock (decklinksrc->mutex);
+ if (videoFrame == NULL) {
+ GST_WARNING_OBJECT (decklinksrc, "video frame is NULL");
+ return S_OK;
+ }
+
+ if (audioFrame == NULL) {
+ GST_WARNING_OBJECT (decklinksrc, "audio frame is NULL");
+ return S_OK;
+ }
+
+ if (videoFrame->GetFlags () & bmdFrameHasNoInputSource) {
+ GST_DEBUG_OBJECT (decklinksrc, "Frame received - No input signal detected");
+ return S_OK;
+ }
+
+ if (g_timecodeFormat != 0) {
+ IDeckLinkTimecode *timecode;
+ if (videoFrame->GetTimecode (g_timecodeFormat, &timecode) == S_OK) {
+ timecode->GetString (&timecodeString);
+ CONVERT_COM_STRING (timecodeString);
}
}
+
+ GST_DEBUG_OBJECT (decklinksrc, "Frame received [%s] - %s - Size: %li bytes",
+ timecodeString != NULL ? timecodeString : "No timecode",
+ "Valid Frame", videoFrame->GetRowBytes () * videoFrame->GetHeight ());
+
+ if (timecodeString)
+ FREE_COM_STRING (timecodeString);
+
+ g_mutex_lock (decklinksrc->mutex);
+ if (decklinksrc->video_frame != NULL) {
+ decklinksrc->dropped_frames++;
+ decklinksrc->video_frame->Release();
+ if (decklinksrc->audio_frame) {
+ decklinksrc->audio_frame->Release();
+ }
+ }
+ videoFrame->AddRef ();
+ decklinksrc->video_frame = videoFrame;
+ if (audioFrame) {
+ audioFrame->AddRef ();
+ decklinksrc->audio_frame = audioFrame;
+ }
+
+ /* increment regardless whether frame was dropped or not */
+ decklinksrc->frame_num++;
+
+ g_cond_signal (decklinksrc->cond);
+ g_mutex_unlock (decklinksrc->mutex);
+
return S_OK;
}
HRESULT
- DeckLinkCaptureDelegate::VideoInputFormatChanged
- (BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode * mode,
- BMDDetectedVideoInputFormatFlags) {
- GST_ERROR ("moo");
+DeckLinkCaptureDelegate::VideoInputFormatChanged (
+ BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode * mode,
+ BMDDetectedVideoInputFormatFlags)
+{
+ 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);
+
+ GST_ERROR_OBJECT (decklinksrc, "unimplemented: video input format changed");
+
return S_OK;
}
diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp
index 88e3559be..4a0c09f08 100644
--- a/sys/decklink/gstdecklink.cpp
+++ b/sys/decklink/gstdecklink.cpp
@@ -190,34 +190,96 @@ gst_decklink_mode_get_template_caps (void)
return caps;
}
-IDeckLink *
-gst_decklink_get_nth_device (int n)
+typedef struct _Device Device;
+struct _Device {
+ IDeckLink *decklink;
+ IDeckLinkInput *input;
+ IDeckLinkOutput *output;
+ IDeckLinkConfiguration *config;
+};
+
+static int n_devices;
+static Device devices[10];
+
+static void
+init_devices (void)
{
IDeckLinkIterator *iterator;
IDeckLink *decklink = NULL;
HRESULT ret;
int i;
+ static gboolean inited = FALSE;
+
+ if (inited) return;
+ inited = TRUE;
iterator = CreateDeckLinkIteratorInstance ();
if (iterator == NULL) {
GST_ERROR ("no driver");
- return NULL;
+ return;
}
+ i = 0;
ret = iterator->Next (&decklink);
- if (ret != S_OK) {
- GST_ERROR ("no card");
- return NULL;
- }
- for (i = 0; i < n; i++) {
- ret = iterator->Next (&decklink);
+ while (ret == S_OK) {
+ devices[i].decklink = decklink;
+
+ ret = decklink->QueryInterface (IID_IDeckLinkInput,
+ (void **) &devices[i].input);
+ if (ret != S_OK) {
+ GST_WARNING ("selected device does not have input interface");
+ return;
+ }
+
+ ret = decklink->QueryInterface (IID_IDeckLinkOutput,
+ (void **) &devices[i].output);
if (ret != S_OK) {
- GST_ERROR ("no card");
- return NULL;
+ GST_WARNING ("selected device does not have output interface");
+ return;
}
+
+ ret = decklink->QueryInterface (IID_IDeckLinkConfiguration,
+ (void **) &devices[i].config);
+ if (ret != S_OK) {
+ GST_WARNING ("selected device does not have config interface");
+ return;
+ }
+
+ ret = iterator->Next (&decklink);
+ i++;
}
- return decklink;
+ n_devices = i;
+
+ iterator->Release();
+}
+
+IDeckLink *
+gst_decklink_get_nth_device (int n)
+{
+ init_devices ();
+ return devices[n].decklink;
+}
+
+IDeckLinkInput *
+gst_decklink_get_nth_input (int n)
+{
+ init_devices ();
+ return devices[n].input;
+}
+
+IDeckLinkOutput *
+gst_decklink_get_nth_output (int n)
+{
+ init_devices ();
+ return devices[n].output;
+}
+
+IDeckLinkConfiguration *
+gst_decklink_get_nth_config (int n)
+{
+ init_devices ();
+ return devices[n].config;
}
static gboolean
diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h
index 77c5cc43a..3b62b4f9b 100644
--- a/sys/decklink/gstdecklink.h
+++ b/sys/decklink/gstdecklink.h
@@ -108,6 +108,8 @@ GstCaps * gst_decklink_mode_get_caps (GstDecklinkModeEnum e);
GstCaps * gst_decklink_mode_get_template_caps (void);
IDeckLink * gst_decklink_get_nth_device (int n);
-
+IDeckLinkInput * gst_decklink_get_nth_input (int n);
+IDeckLinkOutput * gst_decklink_get_nth_output (int n);
+IDeckLinkConfiguration * gst_decklink_get_nth_config (int n);
#endif
diff --git a/sys/decklink/gstdecklinksink.cpp b/sys/decklink/gstdecklinksink.cpp
index dd28a60c6..eeb1c95c8 100644
--- a/sys/decklink/gstdecklinksink.cpp
+++ b/sys/decklink/gstdecklinksink.cpp
@@ -469,12 +469,7 @@ gst_decklink_sink_start (GstDecklinkSink * decklinksink)
return FALSE;
}
- ret = decklinksink->decklink->QueryInterface (IID_IDeckLinkOutput,
- (void **) &decklinksink->output);
- if (ret != S_OK) {
- GST_WARNING ("selected device does not have output interface");
- return FALSE;
- }
+ decklinksink->output = gst_decklink_get_nth_output (decklinksink->device);
decklinksink->output->SetAudioCallback (decklinksink->callback);
@@ -527,11 +522,6 @@ gst_decklink_sink_stop (GstDecklinkSink * decklinksink)
decklinksink->output->DisableAudioOutput ();
decklinksink->output->DisableVideoOutput ();
- decklinksink->output->Release ();
- decklinksink->output = NULL;
- decklinksink->decklink->Release ();
- decklinksink->decklink = NULL;
-
return TRUE;
}
diff --git a/sys/decklink/gstdecklinksrc.cpp b/sys/decklink/gstdecklinksrc.cpp
index 4c0c9b472..ee1c46457 100644
--- a/sys/decklink/gstdecklinksrc.cpp
+++ b/sys/decklink/gstdecklinksrc.cpp
@@ -515,8 +515,6 @@ gst_decklink_src_start (GstElement * element)
{
GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
DeckLinkCaptureDelegate *delegate;
- //IDeckLinkDisplayModeIterator *mode_iterator;
- //IDeckLinkDisplayMode *mode;
BMDAudioSampleType sample_depth;
int channels;
HRESULT ret;
@@ -532,24 +530,19 @@ gst_decklink_src_start (GstElement * element)
return FALSE;
}
- ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkInput,
- (void **) &decklinksrc->input);
- if (ret != S_OK) {
- GST_ERROR ("selected device does not have input interface");
- return FALSE;
- }
+ decklinksrc->input = gst_decklink_get_nth_input (decklinksrc->device);
delegate = new DeckLinkCaptureDelegate ();
delegate->priv = decklinksrc;
- decklinksrc->input->SetCallback (delegate);
-
- ret = decklinksrc->decklink->QueryInterface (IID_IDeckLinkConfiguration,
- (void **) &config);
+ ret = decklinksrc->input->SetCallback (delegate);
if (ret != S_OK) {
- GST_ERROR ("query interface failed");
+ GST_ERROR ("set callback failed (input source)");
return FALSE;
}
+ decklinksrc->config = gst_decklink_get_nth_config (decklinksrc->device);
+ config = decklinksrc->config;
+
switch (decklinksrc->connection) {
default:
case GST_DECKLINK_CONNECTION_SDI:
@@ -613,25 +606,6 @@ gst_decklink_src_start (GstElement * element)
GST_ERROR ("set configuration (audio input connection)");
return FALSE;
}
-#if 0
- ret = decklinksrc->input->GetDisplayModeIterator (&mode_iterator);
- if (ret != S_OK) {
- GST_ERROR ("failed to get display mode iterator");
- return FALSE;
- }
-
- i = 0;
- while (mode_iterator->Next (&mode) == S_OK) {
- const char *mode_name;
-
- mode->GetName (&mode_name);
-
- GST_DEBUG ("%d: mode name: %s", i, mode_name);
-
- mode->Release ();
- i++;
- }
-#endif
mode = gst_decklink_get_mode (decklinksrc->mode);
@@ -667,6 +641,7 @@ static gboolean
gst_decklink_src_stop (GstElement * element)
{
GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (element);
+ //int refcount;
gst_task_stop (decklinksrc->task);
@@ -681,12 +656,6 @@ gst_decklink_src_stop (GstElement * element)
decklinksrc->input->DisableVideoInput ();
decklinksrc->input->DisableAudioInput ();
- decklinksrc->input->Release ();
- decklinksrc->input = NULL;
-
- decklinksrc->decklink->Release ();
- decklinksrc->decklink = NULL;
-
return TRUE;
}
@@ -1456,6 +1425,7 @@ gst_decklinksrc_class_probe_devices (GstElementClass * klass)
n_devices++;
}
}
+ iterator->Release();
probed = TRUE;
}
diff --git a/sys/decklink/gstdecklinksrc.h b/sys/decklink/gstdecklinksrc.h
index 38d00d711..f64a4e645 100644
--- a/sys/decklink/gstdecklinksrc.h
+++ b/sys/decklink/gstdecklinksrc.h
@@ -45,6 +45,7 @@ struct _GstDecklinkSrc
IDeckLink *decklink;
IDeckLinkInput *input;
+ IDeckLinkConfiguration *config;
GMutex *mutex;
GCond *cond;