imperxflexsrc: add timeout property, unlock and unlock_stop methods for better fault handling

This commit is contained in:
Joshua M. Doe 2016-07-06 14:36:59 -04:00
parent f2c86ccd48
commit e876660438
2 changed files with 92 additions and 13 deletions

View File

@ -55,6 +55,8 @@ static gboolean gst_framelinksrc_start (GstBaseSrc * src);
static gboolean gst_framelinksrc_stop (GstBaseSrc * src);
static GstCaps *gst_framelinksrc_get_caps (GstBaseSrc * src, GstCaps * filter);
static gboolean gst_framelinksrc_set_caps (GstBaseSrc * src, GstCaps * caps);
static gboolean gst_framelinksrc_unlock (GstBaseSrc * src);
static gboolean gst_framelinksrc_unlock_stop (GstBaseSrc * src);
static GstFlowReturn gst_framelinksrc_create (GstPushSrc * src,
GstBuffer ** buf);
@ -66,13 +68,15 @@ enum
PROP_FORMAT_FILE,
PROP_NUM_CAPTURE_BUFFERS,
PROP_BOARD,
PROP_CHANNEL
PROP_CHANNEL,
PROP_TIMEOUT
};
#define DEFAULT_PROP_FORMAT_FILE ""
#define DEFAULT_PROP_NUM_CAPTURE_BUFFERS 2
#define DEFAULT_PROP_BOARD 0
#define DEFAULT_PROP_CHANNEL 0
#define DEFAULT_PROP_TIMEOUT 1000
/* pad templates */
@ -113,6 +117,9 @@ gst_framelinksrc_class_init (GstFramelinkSrcClass * klass)
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_framelinksrc_stop);
gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_framelinksrc_get_caps);
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_framelinksrc_set_caps);
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_framelinksrc_unlock);
gstbasesrc_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_framelinksrc_unlock_stop);
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_framelinksrc_create);
@ -136,6 +143,12 @@ gst_framelinksrc_class_init (GstFramelinkSrcClass * klass)
g_param_spec_uint ("channel", "Channel", "Channel number", 0,
1, DEFAULT_PROP_CHANNEL,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_TIMEOUT, g_param_spec_int ("timeout",
"Timeout (ms)",
"Timeout in ms (0 to use default)", 0, G_MAXINT,
DEFAULT_PROP_TIMEOUT, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
}
static void
@ -169,10 +182,13 @@ gst_framelinksrc_init (GstFramelinkSrc * src)
/* initialize member variables */
src->format_file = g_strdup (DEFAULT_PROP_FORMAT_FILE);
src->num_capture_buffers = DEFAULT_PROP_NUM_CAPTURE_BUFFERS;
src->board = DEFAULT_PROP_BOARD;
src->channel = DEFAULT_PROP_CHANNEL;
src->timeout = DEFAULT_PROP_TIMEOUT;
g_mutex_init (&src->mutex);
g_cond_init (&src->cond);
src->stop_requested = FALSE;
src->caps = NULL;
src->buffer = NULL;
@ -207,6 +223,9 @@ gst_framelinksrc_set_property (GObject * object, guint property_id,
case PROP_CHANNEL:
src->channel = g_value_get_uint (value);
break;
case PROP_TIMEOUT:
src->timeout = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -235,6 +254,9 @@ gst_framelinksrc_get_property (GObject * object, guint property_id,
case PROP_CHANNEL:
g_value_set_uint (value, src->channel);
break;
case PROP_TIMEOUT:
g_value_set_int (value, src->timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -251,6 +273,9 @@ gst_framelinksrc_dispose (GObject * object)
/* clean up as possible. may be called multiple times */
g_mutex_clear (&src->mutex);
g_cond_clear (&src->cond);
G_OBJECT_CLASS (gst_framelinksrc_parent_class)->dispose (object);
}
@ -433,17 +458,28 @@ static gboolean
gst_framelinksrc_stop (GstBaseSrc * bsrc)
{
GstFramelinkSrc *src = GST_FRAMELINK_SRC (bsrc);
VCECLB_Error err;
GST_DEBUG_OBJECT (src, "stop");
if (src->acq_started) {
VCECLB_StopGrabEx (src->grabber, src->channel);
err = VCECLB_StopGrabEx (src->grabber, src->channel);
if (err) {
GST_WARNING_OBJECT (src, "Error calling VCECLB_StopGrabEx: %d", err);
}
src->acq_started = FALSE;
}
if (src->grabber) {
VCECLB_ReleaseDMAAccessEx (src->grabber, src->channel);
VCECLB_Done (src->grabber);
err = VCECLB_ReleaseDMAAccessEx (src->grabber, src->channel);
if (err) {
GST_WARNING_OBJECT (src, "Error calling VCECLB_ReleaseDMAAccessEx: %d",
err);
}
err = VCECLB_Done (src->grabber);
if (err) {
GST_WARNING_OBJECT (src, "Error calling VCECLB_Done: %d", err);
}
src->grabber = NULL;
}
@ -502,6 +538,33 @@ unsupported_caps:
return FALSE;
}
static gboolean
gst_framelinksrc_unlock (GstBaseSrc * bsrc)
{
GstFramelinkSrc *src = GST_FRAMELINK_SRC (bsrc);
GST_LOG_OBJECT (src, "unlock");
g_mutex_lock (&src->mutex);
src->stop_requested = TRUE;
g_cond_signal (&src->cond);
g_mutex_unlock (&src->mutex);
return TRUE;
}
static gboolean
gst_framelinksrc_unlock_stop (GstBaseSrc * bsrc)
{
GstFramelinkSrc *src = GST_FRAMELINK_SRC (bsrc);
GST_LOG_OBJECT (src, "unlock_stop");
src->stop_requested = FALSE;
return TRUE;
}
static GstBuffer *
gst_framelinksrc_create_buffer_from_frameinfo (GstFramelinkSrc * src,
VCECLB_FrameInfoEx * pFrameInfo)
@ -631,9 +694,13 @@ gst_framelinksrc_create (GstPushSrc * psrc, GstBuffer ** buf)
{
GstFramelinkSrc *src = GST_FRAMELINK_SRC (psrc);
VCECLB_Error err;
gint64 end_time;
GST_LOG_OBJECT (src, "create");
/* Start acquisition if not already started */
if (G_UNLIKELY (!src->acq_started)) {
GST_LOG_OBJECT (src, "starting acquisition");
err =
VCECLB_StartGrabEx (src->grabber, src->channel, 0,
gst_framelinksrc_callback, src);
@ -647,17 +714,27 @@ gst_framelinksrc_create (GstPushSrc * psrc, GstBuffer ** buf)
/* wait for a buffer to be ready */
g_mutex_lock (&src->mutex);
while (!src->buffer) {
/* TODO: add check for halted acquisition so we don't wait forever */
g_cond_wait (&src->cond, &src->mutex);
}
if (src->buffer) {
*buf = src->buffer;
src->buffer = NULL;
end_time = g_get_monotonic_time () + src->timeout * G_TIME_SPAN_MILLISECOND;
while (!src->buffer && !src->stop_requested) {
if (!g_cond_wait_until (&src->cond, &src->mutex, end_time)) {
g_mutex_unlock (&src->mutex);
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
("Timeout, no data received after %d ms", src->timeout), (NULL));
return GST_FLOW_ERROR;
}
}
*buf = src->buffer;
src->buffer = NULL;
g_mutex_unlock (&src->mutex);
if (src->stop_requested) {
if (*buf != NULL) {
gst_buffer_unref (*buf);
*buf = NULL;
}
return GST_FLOW_FLUSHING;
}
return GST_FLOW_OK;
}

View File

@ -55,6 +55,7 @@ struct _GstFramelinkSrc
guint num_capture_buffers;
guint board;
guint channel;
gint timeout;
GstBuffer *buffer;
@ -65,6 +66,7 @@ struct _GstFramelinkSrc
GMutex mutex;
GCond cond;
gboolean stop_requested;
};
struct _GstFramelinkSrcClass