niimaqsrc: add avoid copy mode

Unfortunately IMAQ only lets you examine one buffer at a time, and elements
like queue store up multiple buffers, so avoid-copy=TRUE can only be used in
pipelines without queues or other such elements.

Also, make property strings static.
This commit is contained in:
Joshua M. Doe 2012-07-03 02:55:34 -04:00
parent 24b7fa4fc3
commit d6fe385cb9
2 changed files with 62 additions and 19 deletions

View File

@ -57,11 +57,13 @@ enum
{ {
PROP_0, PROP_0,
PROP_INTERFACE, PROP_INTERFACE,
PROP_BUFSIZE PROP_BUFSIZE,
PROP_AVOID_COPY
}; };
#define DEFAULT_PROP_INTERFACE "img0" #define DEFAULT_PROP_INTERFACE "img0"
#define DEFAULT_PROP_BUFSIZE 10 #define DEFAULT_PROP_BUFSIZE 10
#define DEFAULT_PROP_AVOID_COPY FALSE
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
@ -458,12 +460,17 @@ gst_niimaqsrc_class_init (GstNiImaqSrcClass * klass)
PROP_INTERFACE, g_param_spec_string ("interface", PROP_INTERFACE, g_param_spec_string ("interface",
"Interface", "Interface",
"NI-IMAQ interface to open", DEFAULT_PROP_INTERFACE, "NI-IMAQ interface to open", DEFAULT_PROP_INTERFACE,
G_PARAM_READWRITE)); G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFSIZE, g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFSIZE,
g_param_spec_int ("buffer-size", g_param_spec_int ("buffer-size",
"Number of frames in the IMAQ ringbuffer", "Number of frames in the IMAQ ringbuffer",
"The number of frames in the IMAQ ringbuffer", 1, G_MAXINT, "The number of frames in the IMAQ ringbuffer", 1, G_MAXINT,
DEFAULT_PROP_BUFSIZE, G_PARAM_READWRITE)); DEFAULT_PROP_BUFSIZE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AVOID_COPY,
g_param_spec_boolean ("avoid-copy",
"Avoid copying",
"Whether to avoid copying (do not use with queues)",
DEFAULT_PROP_AVOID_COPY, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
/* install GstBaseSrc vmethod implementations */ /* install GstBaseSrc vmethod implementations */
gstbasesrc_class->get_caps = gst_niimaqsrc_get_caps; gstbasesrc_class->get_caps = gst_niimaqsrc_get_caps;
@ -497,6 +504,7 @@ gst_niimaqsrc_init (GstNiImaqSrc * niimaqsrc, GstNiImaqSrcClass * g_class)
/* initialize properties */ /* initialize properties */
niimaqsrc->bufsize = DEFAULT_PROP_BUFSIZE; niimaqsrc->bufsize = DEFAULT_PROP_BUFSIZE;
niimaqsrc->interface_name = g_strdup (DEFAULT_PROP_INTERFACE); niimaqsrc->interface_name = g_strdup (DEFAULT_PROP_INTERFACE);
niimaqsrc->avoid_copy = DEFAULT_PROP_AVOID_COPY;
niimaqsrc->frametime_mutex = g_mutex_new (); niimaqsrc->frametime_mutex = g_mutex_new ();
} }
@ -546,6 +554,10 @@ gst_niimaqsrc_set_property (GObject * object, guint prop_id,
break; break;
case PROP_BUFSIZE: case PROP_BUFSIZE:
niimaqsrc->bufsize = g_value_get_int (value); niimaqsrc->bufsize = g_value_get_int (value);
break;
case PROP_AVOID_COPY:
niimaqsrc->avoid_copy = g_value_get_boolean (value);
break;
default: default:
break; break;
} }
@ -564,6 +576,9 @@ gst_niimaqsrc_get_property (GObject * object, guint prop_id, GValue * value,
case PROP_BUFSIZE: case PROP_BUFSIZE:
g_value_set_int (value, niimaqsrc->bufsize); g_value_set_int (value, niimaqsrc->bufsize);
break; break;
case PROP_AVOID_COPY:
g_value_set_boolean (value, niimaqsrc->avoid_copy);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -734,6 +749,13 @@ gst_niimaqsrc_get_timestamp_from_buffer_number (GstNiImaqSrc * niimaqsrc,
return GST_CLOCK_DIFF (niimaqsrc->base_time, abstime); return GST_CLOCK_DIFF (niimaqsrc->base_time, abstime);
} }
static void
gst_niimaqsrc_release_buffer (gpointer data)
{
GstNiImaqSrc *niimaqsrc = GST_NIIMAQSRC (data);
imgSessionReleaseBuffer (niimaqsrc->sid);
}
static GstFlowReturn static GstFlowReturn
gst_niimaqsrc_create (GstPushSrc * psrc, GstBuffer ** buffer) gst_niimaqsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
{ {
@ -741,41 +763,61 @@ gst_niimaqsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstClockTime timestamp; GstClockTime timestamp;
GstClockTime duration; GstClockTime duration;
guint8 *data;
uInt32 copied_number; uInt32 copied_number;
uInt32 copied_index; uInt32 copied_index;
Int32 rval; Int32 rval;
uInt32 dropped; uInt32 dropped;
gboolean no_copy;
/* we can only do a no-copy if strides are property byte aligned */
no_copy = niimaqsrc->avoid_copy && niimaqsrc->width == niimaqsrc->rowpixels;
/* start the IMAQ acquisition session if we haven't done so yet */ /* start the IMAQ acquisition session if we haven't done so yet */
if (!niimaqsrc->session_started) { if (!niimaqsrc->session_started) {
gst_niimaqsrc_start_acquisition (niimaqsrc); gst_niimaqsrc_start_acquisition (niimaqsrc);
} }
ret = if (no_copy) {
gst_pad_alloc_buffer (GST_BASE_SRC_PAD (niimaqsrc), 0, GST_DEBUG_OBJECT (niimaqsrc,
niimaqsrc->framesize, GST_PAD_CAPS (GST_BASE_SRC_PAD (niimaqsrc)), "Sending IMAQ buffer #%d along without copying", niimaqsrc->cumbufnum);
buffer); *buffer = gst_buffer_new ();
if (ret != GST_FLOW_OK) { if (G_UNLIKELY (*buffer == NULL))
GST_ELEMENT_ERROR (niimaqsrc, RESOURCE, FAILED, goto error;
("Failed to allocate buffer"), GST_BUFFER_SIZE (*buffer) = niimaqsrc->framesize;
("Failed to get downstream pad to allocate buffer")); } else {
goto error; GST_DEBUG_OBJECT (niimaqsrc, "Copying IMAQ buffer #%d",
niimaqsrc->cumbufnum);
ret =
gst_pad_alloc_buffer (GST_BASE_SRC_PAD (niimaqsrc), 0,
niimaqsrc->framesize, GST_PAD_CAPS (GST_BASE_SRC_PAD (niimaqsrc)),
buffer);
if (ret != GST_FLOW_OK) {
GST_ELEMENT_ERROR (niimaqsrc, RESOURCE, FAILED,
("Failed to allocate buffer"),
("Failed to get downstream pad to allocate buffer"));
goto error;
}
} }
GST_DEBUG_OBJECT (niimaqsrc, "Copying IMAQ buffer %d", niimaqsrc->cumbufnum); if (no_copy) {
rval =
data = GST_BUFFER_DATA (*buffer); imgSessionExamineBuffer2 (niimaqsrc->sid, niimaqsrc->cumbufnum,
/* TODO: optionally use ExamineBuffer and byteswap in transfer (to offer BIG_ENDIAN) */ &copied_number, &GST_BUFFER_DATA (*buffer));
if (niimaqsrc->width == niimaqsrc->rowpixels) GST_BUFFER_FREE_FUNC (*buffer) = gst_niimaqsrc_release_buffer;
GST_BUFFER_MALLOCDATA (*buffer) = (guint8 *) niimaqsrc;
} else if (niimaqsrc->width == niimaqsrc->rowpixels) {
/* TODO: optionally use ExamineBuffer and byteswap in transfer (to offer BIG_ENDIAN) */
guint8 *data = GST_BUFFER_DATA (*buffer);
rval = rval =
imgSessionCopyBufferByNumber (niimaqsrc->sid, niimaqsrc->cumbufnum, imgSessionCopyBufferByNumber (niimaqsrc->sid, niimaqsrc->cumbufnum,
data, IMG_OVERWRITE_GET_OLDEST, &copied_number, &copied_index); data, IMG_OVERWRITE_GET_OLDEST, &copied_number, &copied_index);
else } else {
guint8 *data = GST_BUFFER_DATA (*buffer);
rval = rval =
imgSessionCopyAreaByNumber (niimaqsrc->sid, niimaqsrc->cumbufnum, 0, 0, imgSessionCopyAreaByNumber (niimaqsrc->sid, niimaqsrc->cumbufnum, 0, 0,
niimaqsrc->height, niimaqsrc->width, data, niimaqsrc->rowpixels, niimaqsrc->height, niimaqsrc->width, data, niimaqsrc->rowpixels,
IMG_OVERWRITE_GET_OLDEST, &copied_number, &copied_index); IMG_OVERWRITE_GET_OLDEST, &copied_number, &copied_index);
}
if (rval) { if (rval) {
gst_niimaqsrc_report_imaq_error (rval); gst_niimaqsrc_report_imaq_error (rval);

View File

@ -52,6 +52,7 @@ struct _GstNiImaqSrc {
/* properties */ /* properties */
gchar *interface_name; gchar *interface_name;
gint bufsize; gint bufsize;
gboolean avoid_copy;
/* image info */ /* image info */
GstVideoFormat format; GstVideoFormat format;