pleorasrc: add multicast and receiver-only support
This commit is contained in:
parent
44dfc350f0
commit
c5ee1a5706
@ -72,7 +72,10 @@ enum
|
|||||||
PROP_DEVICE_INDEX,
|
PROP_DEVICE_INDEX,
|
||||||
PROP_NUM_CAPTURE_BUFFERS,
|
PROP_NUM_CAPTURE_BUFFERS,
|
||||||
PROP_TIMEOUT,
|
PROP_TIMEOUT,
|
||||||
PROP_DETECTION_TIMEOUT
|
PROP_DETECTION_TIMEOUT,
|
||||||
|
PROP_MULTICAST_GROUP,
|
||||||
|
PROP_PORT,
|
||||||
|
PROP_RECEIVER_ONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_PROP_DEVICE ""
|
#define DEFAULT_PROP_DEVICE ""
|
||||||
@ -80,6 +83,10 @@ enum
|
|||||||
#define DEFAULT_PROP_NUM_CAPTURE_BUFFERS 3
|
#define DEFAULT_PROP_NUM_CAPTURE_BUFFERS 3
|
||||||
#define DEFAULT_PROP_TIMEOUT 1000
|
#define DEFAULT_PROP_TIMEOUT 1000
|
||||||
#define DEFAULT_PROP_DETECTION_TIMEOUT 1000
|
#define DEFAULT_PROP_DETECTION_TIMEOUT 1000
|
||||||
|
#define DEFAULT_PROP_MULTICAST_GROUP "239.192.1.1"
|
||||||
|
#define DEFAULT_PROP_PORT 1042
|
||||||
|
#define DEFAULT_PROP_RECEIVER_ONLY FALSE
|
||||||
|
|
||||||
|
|
||||||
#define VIDEO_CAPS_MAKE_BAYER8(format) \
|
#define VIDEO_CAPS_MAKE_BAYER8(format) \
|
||||||
"video/x-bayer, " \
|
"video/x-bayer, " \
|
||||||
@ -167,6 +174,22 @@ gst_pleorasrc_class_init (GstPleoraSrcClass * klass)
|
|||||||
"Timeout in ms to detect GigE cameras", 100,
|
"Timeout in ms to detect GigE cameras", 100,
|
||||||
60000, DEFAULT_PROP_DETECTION_TIMEOUT,
|
60000, DEFAULT_PROP_DETECTION_TIMEOUT,
|
||||||
(GParamFlags) (G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)));
|
(GParamFlags) (G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_MULTICAST_GROUP,
|
||||||
|
g_param_spec_string ("multicast-group", "Multicast group IP address",
|
||||||
|
"The address of the multicast group to join.",
|
||||||
|
DEFAULT_PROP_MULTICAST_GROUP,
|
||||||
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||||
|
GST_PARAM_MUTABLE_READY)));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT,
|
||||||
|
g_param_spec_int ("port", "Multicast port",
|
||||||
|
"The port of the multicast group.", 0,
|
||||||
|
65535, DEFAULT_PROP_PORT,
|
||||||
|
(GParamFlags) (G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_RECEIVER_ONLY,
|
||||||
|
g_param_spec_boolean ("receiver-only", "Receiver only",
|
||||||
|
"Only open video stream, don't open as controller",
|
||||||
|
DEFAULT_PROP_RECEIVER_ONLY,
|
||||||
|
(GParamFlags) (G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -200,6 +223,9 @@ gst_pleorasrc_init (GstPleoraSrc * src)
|
|||||||
src->num_capture_buffers = DEFAULT_PROP_NUM_CAPTURE_BUFFERS;
|
src->num_capture_buffers = DEFAULT_PROP_NUM_CAPTURE_BUFFERS;
|
||||||
src->timeout = DEFAULT_PROP_TIMEOUT;
|
src->timeout = DEFAULT_PROP_TIMEOUT;
|
||||||
src->detection_timeout = DEFAULT_PROP_DETECTION_TIMEOUT;
|
src->detection_timeout = DEFAULT_PROP_DETECTION_TIMEOUT;
|
||||||
|
src->multicast_group= g_strdup (DEFAULT_PROP_MULTICAST_GROUP);
|
||||||
|
src->port = DEFAULT_PROP_PORT;
|
||||||
|
src->receiver_only = DEFAULT_PROP_RECEIVER_ONLY;
|
||||||
|
|
||||||
src->stop_requested = FALSE;
|
src->stop_requested = FALSE;
|
||||||
src->caps = NULL;
|
src->caps = NULL;
|
||||||
@ -232,6 +258,16 @@ gst_pleorasrc_set_property (GObject * object, guint property_id,
|
|||||||
case PROP_DETECTION_TIMEOUT:
|
case PROP_DETECTION_TIMEOUT:
|
||||||
src->detection_timeout = g_value_get_int (value);
|
src->detection_timeout = g_value_get_int (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_MULTICAST_GROUP:
|
||||||
|
g_free (src->multicast_group);
|
||||||
|
src->multicast_group = g_strdup (g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_PORT:
|
||||||
|
src->port = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_RECEIVER_ONLY:
|
||||||
|
src->receiver_only = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -263,6 +299,15 @@ gst_pleorasrc_get_property (GObject * object, guint property_id,
|
|||||||
case PROP_DETECTION_TIMEOUT:
|
case PROP_DETECTION_TIMEOUT:
|
||||||
g_value_set_int (value, src->detection_timeout);
|
g_value_set_int (value, src->detection_timeout);
|
||||||
break;
|
break;
|
||||||
|
case PROP_MULTICAST_GROUP:
|
||||||
|
g_value_set_string (value, src->multicast_group);
|
||||||
|
break;
|
||||||
|
case PROP_PORT:
|
||||||
|
g_value_set_int (value, src->port);
|
||||||
|
break;
|
||||||
|
case PROP_RECEIVER_ONLY:
|
||||||
|
g_value_set_boolean (value, src->receiver_only);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -291,7 +336,10 @@ gst_pleorasrc_finalize (GObject * object)
|
|||||||
src = GST_PLEORA_SRC (object);
|
src = GST_PLEORA_SRC (object);
|
||||||
|
|
||||||
/* clean up object here */
|
/* clean up object here */
|
||||||
g_free (src->device);
|
if (src->device) {
|
||||||
|
g_free (src->device);
|
||||||
|
src->device = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (src->caps) {
|
if (src->caps) {
|
||||||
gst_caps_unref (src->caps);
|
gst_caps_unref (src->caps);
|
||||||
@ -483,27 +531,42 @@ gst_pleorasrc_setup_device (GstPleoraSrc * src)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "Trying to connect to device '%s'",
|
/* open as controller by connecting to device */
|
||||||
device_info->GetDisplayID ().GetAscii ());
|
if (!src->receiver_only) {
|
||||||
src->device = PvDevice::CreateAndConnect (device_info, &pvRes);
|
GST_DEBUG_OBJECT (src, "Trying to connect to device '%s'",
|
||||||
if (src->device == NULL) {
|
device_info->GetDisplayID ().GetAscii ());
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
|
||||||
("Unable to create and connect to device"), (NULL));
|
src->device = PvDevice::CreateAndConnect (device_info, &pvRes);
|
||||||
return FALSE;
|
if (src->device == NULL) {
|
||||||
}
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||||
GST_DEBUG_OBJECT (src, "Connected to device");
|
("Unable to create and connect to device"), (NULL));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (src, "Connected to device");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_info->GetType() == PvDeviceInfoTypeGEV ||
|
||||||
|
device_info->GetType() == PvDeviceInfoTypePleoraProtocol) {
|
||||||
|
GST_DEBUG_OBJECT (src, "Opening multicast stream");
|
||||||
|
PvStreamGEV *stream = new PvStreamGEV;
|
||||||
|
// FIXME: need to add prop for enabling multicast
|
||||||
|
stream->Open(device_info->GetConnectionID(), src->multicast_group, src->port);
|
||||||
|
src->stream = stream;
|
||||||
|
} else {
|
||||||
|
src->stream =
|
||||||
|
PvStream::CreateAndOpen (device_info->GetConnectionID (), &pvRes);
|
||||||
|
}
|
||||||
|
|
||||||
src->stream =
|
|
||||||
PvStream::CreateAndOpen (device_info->GetConnectionID (), &pvRes);
|
|
||||||
if (src->stream == NULL) {
|
if (src->stream == NULL) {
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||||
("Unable to create and connect to device"), (NULL));
|
("Unable to create and connect to device"), (NULL));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (src, "Stream created for device");
|
GST_DEBUG_OBJECT (src, "Stream created for device");
|
||||||
|
|
||||||
|
/* if acting as a GigE controller configure stream */
|
||||||
PvDeviceGEV *lDeviceGEV = dynamic_cast < PvDeviceGEV * >(src->device);
|
PvDeviceGEV *lDeviceGEV = dynamic_cast < PvDeviceGEV * >(src->device);
|
||||||
if (lDeviceGEV != NULL) {
|
if (!src->receiver_only && lDeviceGEV != NULL) {
|
||||||
PvStreamGEV *lStreamGEV = static_cast < PvStreamGEV * >(src->stream);
|
PvStreamGEV *lStreamGEV = static_cast < PvStreamGEV * >(src->stream);
|
||||||
|
|
||||||
// Negotiate packet size
|
// Negotiate packet size
|
||||||
@ -521,9 +584,7 @@ gst_pleorasrc_setup_device (GstPleoraSrc * src)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t lSize = src->device->GetPayloadSize ();
|
|
||||||
src->pipeline->SetBufferCount (src->num_capture_buffers);
|
src->pipeline->SetBufferCount (src->num_capture_buffers);
|
||||||
src->pipeline->SetBufferSize (lSize);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -743,17 +804,6 @@ gst_pleorasrc_start (GstBaseSrc * bsrc)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvGenParameterArray *lDeviceParams = src->device->GetParameters ();
|
|
||||||
PvGenCommand *start_cmd =
|
|
||||||
dynamic_cast < PvGenCommand * >(lDeviceParams->Get ("AcquisitionStart"));
|
|
||||||
|
|
||||||
if (start_cmd == NULL) {
|
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
|
||||||
("Failed to get device AcquisitionStart parameter"), (NULL));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Note: the pipeline must be initialized before we start acquisition */
|
/* Note: the pipeline must be initialized before we start acquisition */
|
||||||
GST_DEBUG_OBJECT (src, "Starting pipeline");
|
GST_DEBUG_OBJECT (src, "Starting pipeline");
|
||||||
pvRes = src->pipeline->Start ();
|
pvRes = src->pipeline->Start ();
|
||||||
@ -763,18 +813,30 @@ gst_pleorasrc_start (GstBaseSrc * bsrc)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
pvRes = src->device->StreamEnable ();
|
/* command stream to start */
|
||||||
if (!pvRes.IsOK ()) {
|
if (!src->receiver_only) {
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to enable stream"),
|
PvGenParameterArray *lDeviceParams = src->device->GetParameters ();
|
||||||
(NULL));
|
PvGenCommand *start_cmd =
|
||||||
goto error;
|
dynamic_cast < PvGenCommand * >(lDeviceParams->Get ("AcquisitionStart"));
|
||||||
}
|
|
||||||
|
|
||||||
pvRes = start_cmd->Execute ();
|
if (start_cmd == NULL) {
|
||||||
if (!pvRes.IsOK ()) {
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to start acquisition"),
|
("Failed to get device AcquisitionStart parameter"), (NULL));
|
||||||
(NULL));
|
goto error;
|
||||||
goto error;
|
}
|
||||||
|
pvRes = src->device->StreamEnable ();
|
||||||
|
if (!pvRes.IsOK ()) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to enable stream"),
|
||||||
|
(NULL));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pvRes = start_cmd->Execute ();
|
||||||
|
if (!pvRes.IsOK ()) {
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to start acquisition"),
|
||||||
|
(NULL));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -797,7 +859,7 @@ error:
|
|||||||
src->device = NULL;
|
src->device = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -806,11 +868,13 @@ gst_pleorasrc_stop (GstBaseSrc * bsrc)
|
|||||||
GstPleoraSrc *src = GST_PLEORA_SRC (bsrc);
|
GstPleoraSrc *src = GST_PLEORA_SRC (bsrc);
|
||||||
GST_DEBUG_OBJECT (src, "stop");
|
GST_DEBUG_OBJECT (src, "stop");
|
||||||
|
|
||||||
PvGenParameterArray *lDeviceParams = src->device->GetParameters ();
|
if (!src->receiver_only) {
|
||||||
PvGenCommand *lStop =
|
PvGenParameterArray *lDeviceParams = src->device->GetParameters ();
|
||||||
dynamic_cast < PvGenCommand * >(lDeviceParams->Get ("AcquisitionStop"));
|
PvGenCommand *lStop =
|
||||||
lStop->Execute ();
|
dynamic_cast < PvGenCommand * >(lDeviceParams->Get ("AcquisitionStop"));
|
||||||
src->device->StreamDisable ();
|
lStop->Execute ();
|
||||||
|
src->device->StreamDisable ();
|
||||||
|
}
|
||||||
src->pipeline->Stop ();
|
src->pipeline->Stop ();
|
||||||
|
|
||||||
if (src->pipeline) {
|
if (src->pipeline) {
|
||||||
@ -841,7 +905,7 @@ gst_pleorasrc_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
|||||||
GstPleoraSrc *src = GST_PLEORA_SRC (bsrc);
|
GstPleoraSrc *src = GST_PLEORA_SRC (bsrc);
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
if (src->pipeline == NULL) {
|
if (src->caps == NULL) {
|
||||||
caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (src));
|
caps = gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (src));
|
||||||
} else {
|
} else {
|
||||||
caps = gst_caps_copy (src->caps);
|
caps = gst_caps_copy (src->caps);
|
||||||
@ -968,21 +1032,39 @@ gst_pleorasrc_create (GstPushSrc * psrc, GstBuffer ** buf)
|
|||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
GstClockTime clock_time;
|
GstClockTime clock_time;
|
||||||
PvBuffer *pvbuffer;
|
PvBuffer *pvbuffer;
|
||||||
|
PvImage *pvimage;
|
||||||
|
|
||||||
GST_LOG_OBJECT (src, "create");
|
GST_LOG_OBJECT (src, "create");
|
||||||
|
|
||||||
pvRes = src->pipeline->RetrieveNextBuffer (&pvbuffer, 1000, &opRes);
|
while (TRUE) {
|
||||||
if (pvbuffer->GetPayloadType () != PvPayloadTypeImage) {
|
pvRes = src->pipeline->RetrieveNextBuffer (&pvbuffer, src->timeout, &opRes);
|
||||||
/* TODO: are non-image buffers normal? */
|
if (!pvRes.IsOK()) {
|
||||||
GST_ERROR_OBJECT (src, "Got buffer with non-image data");
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Failed to retrieve buffer in timeout (%d ms): 0x%04x, '%s'", src->timeout, pvRes.GetCode(), pvRes.GetDescription().GetAscii()), (NULL));
|
||||||
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
return GST_FLOW_ERROR;
|
||||||
("Got buffer with non-image data"), (NULL));
|
}
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
|
// continue if we get a bad frame
|
||||||
|
if (!opRes.IsOK()) {
|
||||||
|
GST_WARNING_OBJECT(src, "Failed to get buffer: 0x%04x, '%s'", opRes.GetCode(), opRes.GetCodeString().GetAscii());
|
||||||
|
src->pipeline->ReleaseBuffer(pvbuffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvbuffer->GetPayloadType () != PvPayloadTypeImage) {
|
||||||
|
/* TODO: are non-image buffers normal? */
|
||||||
|
GST_ERROR_OBJECT (src, "Got buffer with non-image data");
|
||||||
|
GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
|
||||||
|
("Got buffer with non-image data"), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pvimage = pvbuffer->GetImage ();
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PvImage *pvimage = pvbuffer->GetImage ();
|
const char *caps_string =
|
||||||
|
gst_pleorasrc_pixel_type_to_gst_caps_string (pvimage->GetPixelType ());
|
||||||
const char *caps_string =
|
|
||||||
gst_pleorasrc_pixel_type_to_gst_caps_string (pvimage->GetPixelType ());
|
|
||||||
|
|
||||||
/* TODO: cache previous caps_string */
|
/* TODO: cache previous caps_string */
|
||||||
if (caps_string != NULL) {
|
if (caps_string != NULL) {
|
||||||
|
|||||||
@ -52,6 +52,9 @@ struct _GstPleoraSrc
|
|||||||
guint num_capture_buffers;
|
guint num_capture_buffers;
|
||||||
gint timeout;
|
gint timeout;
|
||||||
gint detection_timeout;
|
gint detection_timeout;
|
||||||
|
gchar *multicast_group;
|
||||||
|
gint port;
|
||||||
|
gboolean receiver_only;
|
||||||
|
|
||||||
guint32 last_frame_count;
|
guint32 last_frame_count;
|
||||||
guint32 total_dropped_frames;
|
guint32 total_dropped_frames;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user