diff options
author | David Schleef <ds@schleef.org> | 2012-09-23 13:15:20 -0700 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.net> | 2012-09-23 21:27:36 +0100 |
commit | 65a1f79bcbaf1089888a7e8bba89e5c2c2b6457e (patch) | |
tree | 94eb7d298a18f3a56b174053f0e228d92074107b /sys | |
parent | dd66252f23b198d03671ed2c913623ccd7a518a7 (diff) | |
download | gstreamer-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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/decklink/capture.cpp | 105 | ||||
-rw-r--r-- | sys/decklink/gstdecklink.cpp | 86 | ||||
-rw-r--r-- | sys/decklink/gstdecklink.h | 4 | ||||
-rw-r--r-- | sys/decklink/gstdecklinksink.cpp | 12 | ||||
-rw-r--r-- | sys/decklink/gstdecklinksrc.cpp | 46 | ||||
-rw-r--r-- | sys/decklink/gstdecklinksrc.h | 1 |
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; |