Closed mkaivs closed 3 years ago
Generally you shouldn't need that long grab-timeout
. You can try increasing frame-drop-limit
. Though both these configurations are too rough and straight-forward.
If you are experiencing grab errors probably the rest of your pipeline is too slow. Try running your pipeline with just pylonsrc, some capsfilter probably and a fakesink.
If that doesn't help, you should manage bandwidth configuration. See this. Transport layer features can be set with packet-size
, inter-packet-delay
, frame-trans-delay
, bandwidth-reserve
and bandwidth-reserve-acc
plugin properties.
If you really want to leave 1 min timeout, then you could try putting PylonWaitObjectSignal(src->waitObject)
in whichever function (probably gst_pylonsrc_stop
) is called to interrupt a plugin. But I'm almost sure that gst_pylonsrc_stop
is called in the main thread as well as gst_pylonsrc_create
which is waiting in this case
@mrstecklo thank you for the pointer. The timeout is set to wait for objects that will be captured by the camera rather than for the pipeline. I follow your advice and modified the gst_pylonsrc_stop
function as follow:
static gboolean
gst_pylonsrc_stop (GstBaseSrc * bsrc)
{
GstPylonSrc *src = GST_PYLONSRC (bsrc);
GST_DEBUG_OBJECT (src, "stop");
// interrupt grab-timeout
GST_DEBUG_OBJECT (src, "singal wait object");
PylonWaitObjectSignal(src->waitObject);
pylonc_disconnect_camera (src);
return TRUE;
}
But it doesn't work:
^C
Posting UserInterrupt message to bus.
UserInterrupt message posted, stopping pipeline...
Call g_main_loop_quit(loop);
Returned, stopping playback
Call gst_element_set_state(pipeline, GST_STATE_NULL);
0:01:03.759489213 9727 0x55da5e5d8400 ERROR pylonsrc gstpylonsrc.c:4092:gst_pylonsrc_create:<camera> Camera couldn't prepare the buffer in time. Probably dead.
0:01:03.759616837 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4161:gst_pylonsrc_stop:<camera> stop
0:01:03.759656304 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4164:gst_pylonsrc_stop:<camera> singal wait object
0:01:03.793825385 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4219:pylonc_disconnect_camera:<camera> Camera disconnected.
Deleting pipeline
0:01:03.886512759 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4175:gst_pylonsrc_dispose:<camera> dispose
0:01:03.886539016 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4183:gst_pylonsrc_finalize:<camera> finalize
0:01:03.889187367 9727 0x55d9fa5cfc00 DEBUG pylonsrc gstpylonsrc.c:4201:gst_pylonsrc_finalize:<camera> Last object finalized
Exit program
gst_pylonsrc_stop
is only called after gst_pylonsrc_create
timeout. I checked the gst_pylonsrc_create
and gst_pylonsrc_stop
is not called there.
I have also tried to use PylonWaitObjectWaitEx
instead of PylonWaitObjectWait
in the gst_pylonsrc_create
function but that doesn't work either.
How do I go from here?
The problem is that most functions are called in one thread. If I'm not mistaken this 0x55da5e5d8400
in gstreamer output is a thread ID
@mrstecklo
You're correct 0x55da5e5d8400
is the thread ID. The gst_pylonsrc_stop
is called from the main thread only after the gst_pylonsrc_create
returned. You mentioned that "The problem is that most functions are called in one thread.", I'm not sure what you meant by that?
Regarding your suggestions, I have tried called gst_base_src_set_async
from gst_pylonsrc_init
as follow:
@@ -882,6 +990,8 @@ gst_pylonsrc_init (GstPylonSrc * src)
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
+
+ gst_base_src_set_async(GST_BASE_SRC (src), TRUE);
}
I still wasn't able to interrupt the gst_pylonsrc_create
function.
I also tried to signal the wait object within the gst_pylonsrc_create
by creating a new thread:
gpointer signal_wait_object(gpointer data)
{
sleep(5);
GST_DEBUG("Signal wait object %p, %ld, %d", g_thread_self(), syscall(__NR_gettid), getpid());
PYLON_WAITOBJECT_HANDLE *wait_object = (PYLON_WAITOBJECT_HANDLE *)data;
GENAPIC_RESULT res = PylonWaitObjectSignal(*wait_object);
if(res != GENAPI_E_OK)
{
GST_DEBUG("Fail to singal wait object");
char* errMsg;
size_t length;
GenApiGetLastErrorMessage( NULL, &length );
errMsg = (char*) malloc( length );
GenApiGetLastErrorMessage( errMsg, &length );
GST_DEBUG("PylonC error: %s (%#08x).\n", errMsg, (unsigned int) res);
free(errMsg);
GenApiGetLastErrorDetail( NULL, &length );
errMsg = (char*) malloc( length );
GenApiGetLastErrorDetail( errMsg, &length );
GST_DEBUG("PylonC error: %s\n", errMsg);
free(errMsg);
}
return wait_object;
}
static GstFlowReturn
gst_pylonsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
{
// code not shown
GThread * interrupt_thread = g_thread_new (
"interrupt_thread",
signal_wait_object,
&src->waitObject);
g_thread_unref(interrupt_thread);
// Wait for the buffer to be filled (up to n ms). Can fail on large frames if timeout set too low.
GST_DEBUG_OBJECT (src, "Waiting for triger ... %p, %ld, %d", g_thread_self(), syscall(__NR_gettid), getpid());
res = PylonWaitObjectWait (src->waitObject, src->grabtimeout, &bufferReady);
// code not shown
}
The output:
0:00:03.738156463 9151 0x5629ebc0e8a0 DEBUG pylonsrc gstpylonsrc.c:4236:gst_pylonsrc_create:<camera> Waiting for triger ... 0x5629ebc0e8a0, 9198, 9151
0:00:08.738424676 9151 0x7f76d400aa30 DEBUG pylonsrc gstpylonsrc.c:4184:signal_wait_object: Signal wait object 0x7f76d400aa30, 9201, 9151
0:00:08.738673703 9151 0x7f76d400aa30 DEBUG pylonsrc gstpylonsrc.c:4190:signal_wait_object: Fail to singal wait object
0:00:08.738704197 9151 0x7f76d400aa30 DEBUG pylonsrc gstpylonsrc.c:4196:signal_wait_object: PylonC error: PylonC error #c2000002 'Failed to signal wait object.' (0xc2000002).
0:00:08.738721511 9151 0x7f76d400aa30 DEBUG pylonsrc gstpylonsrc.c:4201:signal_wait_object: PylonC error: Function 'PylonWaitObjectSignal' failed in source file '../../../../../../../Pylon/PylonC/PylonC/PylonC.cpp' line #3127
Caused by an exception thrown from source file '../../../../../../../Pylon/PylonC/PylonC/PylonC.cpp' line #3123.
Wait object cannot be signaled
So the wait object cannot be signalled externally?
@mkaivs
You mentioned that "The problem is that most functions are called in one thread.", I'm not sure what you meant by that?
I mean that calling PylonWaitObjectSignal
in the same thread as PylonWaitObjectWait
is useless. And that is what GStreamer does by default. So I hoped that calling PylonWaitObjectSignal
from a new thread would help. Seems like it doesn't. I'm not really familiar with Pylon wait objects.
Probably that is not the point, but I'm confused with your address-off/indirection dance around waitObject
.
PYLON_WAITOBJECT_HANDLE
is a pointer itself. So you can pass it directly to g_thread_new
gpointer signal_wait_object(gpointer data)
{
...
PYLON_WAITOBJECT_HANDLE wait_object = (PYLON_WAITOBJECT_HANDLE) data;
...
}
static GstFlowReturn
gst_pylonsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
{
...
GThread * interrupt_thread = g_thread_new (
"interrupt_thread",
signal_wait_object,
src->waitObject);
...
}
The timeout is set to wait for objects that will be captured by the camera rather than for the pipeline
I still don't understand what objects is your camera waiting for so long.
@mrstecklo,
Thank you for the clarification. I read the pylon doc and found this:
pylon C provides a generalized mechanism for applications to wait for externally generated events, based on the concepts of wait objects and wait object containers. Wait objects provide an abstraction layer for operating system-specific synchronization mechanisms. Events in pylon C include image data that become available at a stream grabber (see Retrieving Grabbed Images), or event data that become available at an event grabber. With wait objects, pylon C provides a mechanism for applications to wait for these events. Moreover, applications can create wait objects of their own that can be explicitly signaled.
So the reason PylonWaitObjectSignal
failed is because the wait object of the stream grabber cannot be signalled by the application.
I have a pipeline that makes use of the
pylonsrc
plugin, it's in trigger mode withgrab-timeout
set to 60000 ms (1 min). When user press CTRL+C, the bus will handle it by stopping the mainloop, and subsequently, callgst_element_set_state(pipeline, GST_STATE_NULL);
, however, the program will wait for thegrab-timeout
amount before fully exit. Is there a way interrupt thegrab-timeout
itself?