diff --git a/Gir_GstCheck.toml b/Gir_GstCheck.toml new file mode 100644 index 000000000..e053f940e --- /dev/null +++ b/Gir_GstCheck.toml @@ -0,0 +1,33 @@ +[options] +girs_dir = "gir-files" +library = "GstCheck" +version = "1.0" +min_cfg_version = "1.8" +target_path = "gstreamer-check" +work_mode = "normal" +concurrency = "send+sync" +generate_safety_asserts = true +single_version_file = true + +external_libraries = [ + "GLib", + "GObject", + "Gst", +] + +generate = [ + "GstCheck.TestClock", +] + +manual = [ + "GObject.Object", + "Gst.Object", + "Gst.Clock", + "Gst.ClockTimeDiff", + "Gst.ClockType", +] + +[[object]] +name = "Gst.ClockTime" +status = "manual" +conversion_type = "scalar" diff --git a/gir-files/GstCheck-1.0.gir b/gir-files/GstCheck-1.0.gir new file mode 100644 index 000000000..e0c736714 --- /dev/null +++ b/gir-files/GstCheck-1.0.gir @@ -0,0 +1,2686 @@ + + + + + + + + + + + + #GstHarness is meant to make writing unit test for GStreamer much easier. +It can be thought of as a way of treating a #GstElement as a black box, +deterministically feeding it data, and controlling what data it outputs. + +The basic structure of #GstHarness is two "floating" #GstPads that connect +to the harnessed #GstElement src and sink #GstPads like so: + +|[ + __________________________ + _____ | _____ _____ | _____ +| | | | | | | | | | +| src |--+-| sink| Element | src |-+--| sink| +|_____| | |_____| |_____| | |_____| + |__________________________| + +]| + +With this, you can now simulate any environment the #GstElement might find +itself in. By specifying the #GstCaps of the harness #GstPads, using +functions like gst_harness_set_src_caps() or gst_harness_set_sink_caps_str(), +you can test how the #GstElement interacts with different caps sets. + +Your harnessed #GstElement can of course also be a bin, and using +gst_harness_new_parse() supporting standard gst-launch syntax, you can +easily test a whole pipeline instead of just one element. + +You can then go on to push #GstBuffers and #GstEvents on to the srcpad, +using functions like gst_harness_push() and gst_harness_push_event(), and +then pull them out to examine them with gst_harness_pull() and +gst_harness_pull_event(). + +## A simple buffer-in buffer-out example + +|[<!-- language="C" --> + #include <gst/gst.h> + #include <gst/check/gstharness.h> + GstHarness *h; + GstBuffer *in_buf; + GstBuffer *out_buf; + + // attach the harness to the src and sink pad of GstQueue + h = gst_harness_new ("queue"); + + // we must specify a caps before pushing buffers + gst_harness_set_src_caps_str (h, "mycaps"); + + // create a buffer of size 42 + in_buf = gst_harness_create_buffer (h, 42); + + // push the buffer into the queue + gst_harness_push (h, in_buf); + + // pull the buffer from the queue + out_buf = gst_harness_pull (h); + + // validate the buffer in is the same as buffer out + fail_unless (in_buf == out_buf); + + // cleanup + gst_buffer_unref (out_buf); + gst_harness_teardown (h); + + ]| + +Another main feature of the #GstHarness is its integration with the +#GstTestClock. Operating the #GstTestClock can be very challenging, but +#GstHarness simplifies some of the most desired actions a lot, like wanting +to manually advance the clock while at the same time releasing a #GstClockID +that is waiting, with functions like gst_harness_crank_single_clock_wait(). + +#GstHarness also supports sub-harnesses, as a way of generating and +validating data. A sub-harness is another #GstHarness that is managed by +the "parent" harness, and can either be created by using the standard +gst_harness_new type functions directly on the (GstHarness *)->src_harness, +or using the much more convenient gst_harness_add_src() or +gst_harness_add_sink_parse(). If you have a decoder-element you want to test, +(like vp8dec) it can be very useful to add a src-harness with both a +src-element (videotestsrc) and an encoder (vp8enc) to feed the decoder data +with different configurations, by simply doing: + +|[<!-- language="C" --> + GstHarness * h = gst_harness_new (h, "vp8dec"); + gst_harness_add_src_parse (h, "videotestsrc is-live=1 ! vp8enc", TRUE); +]| + +and then feeding it data with: + +|[<!-- language="C" --> +gst_harness_push_from_src (h); +]| + + the element inside the harness + + + + the internal harness source pad + + + + the internal harness sink pad + + + + the source (input) harness (if any) + + + + the sink (output) harness (if any) + + + + + + + Adds a #GstElement to an empty #GstHarness + +MT safe. + + + + + + a #GstHarness + + + + a #GstElement to add to the harness (transfer none) + + + + a #GstStaticPadTemplate describing the harness srcpad. +%NULL will not create a harness srcpad. + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. Can be a static or request +or a sometimes pad that has been added. %NULL will not get/request a sinkpad +from the element. (Like if the element is a src.) + + + + a #GstStaticPadTemplate describing the harness sinkpad. +%NULL will not create a harness sinkpad. + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad, similar to the +@element_sinkpad_name. + + + + + + Links the specified #GstPad the @GstHarness srcpad. + +MT safe. + + + + + + a #GstHarness + + + + a #GstPad to link to the harness srcpad + + + + + + Links the specified #GstPad the @GstHarness sinkpad. This can be useful if +perhaps the srcpad did not exist at the time of creating the harness, +like a demuxer that provides a sometimes-pad after receiving data. + +MT safe. + + + + + + a #GstHarness + + + + a #GstPad to link to the harness sinkpad + + + + + + Parses the @launchline and puts that in a #GstBin, +and then attches the supplied #GstHarness to the bin. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar describing a gst-launch type line + + + + + + A convenience function to allows you to call gst_pad_add_probe on a +#GstPad of a #GstElement that are residing inside the #GstHarness, +by using normal gst_pad_add_probe syntax + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with a #GstElementFactory name + + + + a #gchar with the name of the pad to attach the probe to + + + + a #GstPadProbeType (see gst_pad_add_probe) + + + + a #GstPadProbeCallback (see gst_pad_add_probe) + + + + a #gpointer (see gst_pad_add_probe) + + + + a #GDestroyNotify (see gst_pad_add_probe) + + + + + + Add api with params as one of the supported metadata API to propose when +receiving an allocation query. + +MT safe. + + + + + + a #GstHarness + + + + a metadata API + + + + API specific parameters + + + + + + Similar to gst_harness_add_sink_harness, this is a convenience to +directly create a sink-harness using the @sink_element_name name specified. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with the name of a #GstElement + + + + + + Similar to gst_harness_add_src, this allows you to send the data coming out +of your harnessed #GstElement to a sink-element, allowing to test different +responses the element output might create in sink elements. An example might +be an existing sink providing some analytical data on the input it receives that +can be useful to your testing. If the goal is to test a sink-element itself, +this is better achieved using gst_harness_new directly on the sink. + +If a sink-harness already exists it will be replaced. + +MT safe. + + + + + + a #GstHarness + + + + a #GstHarness to be added as a sink-harness. + + + + + + Similar to gst_harness_add_sink, this allows you to specify a launch-line +instead of just an element name. See gst_harness_add_src_parse for details. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with the name of a #GstElement + + + + + + Similar to gst_harness_add_src_harness, this is a convenience to +directly create a src-harness using the @src_element_name name specified. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with the name of a #GstElement + + + + a #gboolean specifying if the #GstElement uses +gst_clock_wait_id internally. + + + + + + A src-harness is a great way of providing the #GstHarness with data. +By adding a src-type #GstElement, it is then easy to use functions like +gst_harness_push_from_src or gst_harness_src_crank_and_push_many +to provide your harnessed element with input. The @has_clock_wait variable +is a great way to control you src-element with, in that you can have it +produce a buffer for you by simply cranking the clock, and not have it +spin out of control producing buffers as fast as possible. + +If a src-harness already exists it will be replaced. + +MT safe. + + + + + + a #GstHarness + + + + a #GstHarness to be added as a src-harness. + + + + a #gboolean specifying if the #GstElement uses +gst_clock_wait_id internally. + + + + + + Similar to gst_harness_add_src, this allows you to specify a launch-line, +which can be useful for both having more then one #GstElement acting as your +src (Like a src producing raw buffers, and then an encoder, providing encoded +data), but also by allowing you to set properties like "is-live" directly on +the elements. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar describing a gst-launch type line + + + + a #gboolean specifying if the #GstElement uses +gst_clock_wait_id internally. + + + + + + The number of #GstBuffers currently in the #GstHarness sinkpad #GAsyncQueue + +MT safe. + + a #guint number of buffers in the queue + + + + + a #GstHarness + + + + + + The total number of #GstBuffers that has arrived on the #GstHarness sinkpad. +This number includes buffers that have been dropped as well as buffers +that have already been pulled out. + +MT safe. + + a #guint number of buffers received + + + + + a #GstHarness + + + + + + Similar to gst_harness_crank_single_clock_wait(), this is the function to use +if your harnessed element(s) are using more then one gst_clock_id_wait. +Failing to do so can (and will) make it racy which #GstClockID you actually +are releasing, where as this function will process all the waits at the +same time, ensuring that one thread can't register another wait before +both are released. + +MT safe. + + a @gboolean %TRUE if the "crank" was successful, %FALSE if not. + + + + + a #GstHarness + + + + a #guint describing the number of #GstClockIDs to crank + + + + + + A "crank" consists of three steps: +1: Wait for a #GstClockID to be registered with the #GstTestClock. +2: Advance the #GstTestClock to the time the #GstClockID is waiting for. +3: Release the #GstClockID wait. +Together, this provides an easy way to not have to think about the details +around clocks and time, but still being able to write deterministic tests +that are dependent on this. A "crank" can be though of as the notion of +manually driving the clock forward to its next logical step. + +MT safe. + + a @gboolean %TRUE if the "crank" was successful, %FALSE if not. + + + + + a #GstHarness + + + + + + Allocates a buffer using a #GstBufferPool if present, or else using the +configured #GstAllocator and #GstAllocationParams + +MT safe. + + a #GstBuffer of size @size + + + + + a #GstHarness + + + + a #gsize specifying the size of the buffer + + + + + + Allows you to dump the #GstBuffers the #GstHarness sinkpad #GAsyncQueue +to a file. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with a the name of a file + + + + + + The number of #GstEvents currently in the #GstHarness sinkpad #GAsyncQueue + +MT safe. + + a #guint number of events in the queue + + + + + a #GstHarness + + + + + + The total number of #GstEvents that has arrived on the #GstHarness sinkpad +This number includes events handled by the harness as well as events +that have already been pulled out. + +MT safe. + + a #guint number of events received + + + + + a #GstHarness + + + + + + Most useful in conjunction with gst_harness_new_parse, this will scan the +#GstElements inside the #GstHarness, and check if any of them matches +@element_name. Typical usecase being that you need to access one of the +harnessed elements for properties and/or signals. + +MT safe. + + a #GstElement or %NULL if not found + + + + + a #GstHarness + + + + a #gchar with a #GstElementFactory name + + + + + + A convenience function to allows you to call g_object_get on a #GstElement +that are residing inside the #GstHarness, by using normal g_object_get +syntax. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with a #GstElementFactory name + + + + a #gchar with the first property name + + + + return location for the first property, followed optionally by more + name/return location pairs, followed by %NULL + + + + + + Gets the @allocator and its @params that has been decided to use after an +allocation query. + +MT safe. + + + + + + a #GstHarness + + + + the #GstAllocator used + + + + the #GstAllocationParams of + @allocator + + + + + + Get the timestamp of the last #GstBuffer pushed on the #GstHarness srcpad, +typically with gst_harness_push or gst_harness_push_from_src. + +MT safe. + + a #GstClockTime with the timestamp or %GST_CLOCK_TIME_NONE if no +#GstBuffer has been pushed on the #GstHarness srcpad + + + + + a #GstHarness + + + + + + Get the #GstTestClock. Useful if specific operations on the testclock is +needed. + +MT safe. + + a #GstTestClock, or %NULL if the testclock is not +present. + + + + + a #GstHarness + + + + + + This will set the harnessed #GstElement to %GST_STATE_PLAYING. +#GstElements without a sink-#GstPad and with the %GST_ELEMENT_FLAG_SOURCE +flag set is considered a src #GstElement +Non-src #GstElements (like sinks and filters) are automatically set to +playing by the #GstHarness, but src #GstElements are not to avoid them +starting to produce buffers. +Hence, for src #GstElement you must call gst_harness_play() explicitly. + +MT safe. + + + + + + a #GstHarness + + + + + + Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. The pull +will timeout in 60 seconds. This is the standard way of getting a buffer +from a harnessed #GstElement. + +MT safe. + + a #GstBuffer or %NULL if timed out. + + + + + a #GstHarness + + + + + + Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad. +Timeouts after 60 seconds similar to gst_harness_pull. + +MT safe. + + a #GstEvent or %NULL if timed out. + + + + + a #GstHarness + + + + + + Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad. +Timeouts after 60 seconds similar to gst_harness_pull. + +MT safe. + + a #GstEvent or %NULL if timed out. + + + + + a #GstHarness + + + + + + Pushes a #GstBuffer on the #GstHarness srcpad. The standard way of +interacting with an harnessed element. + +MT safe. + + a #GstFlowReturn with the result from the push + + + + + a #GstHarness + + + + a #GstBuffer to push + + + + + + Basically a gst_harness_push and a gst_harness_pull in one line. Reflects +the fact that you often want to do exactly this in your test: Push one buffer +in, and inspect the outcome. + +MT safe. + + a #GstBuffer or %NULL if timed out. + + + + + a #GstHarness + + + + a #GstBuffer to push + + + + + + Pushes an #GstEvent on the #GstHarness srcpad. + +MT safe. + + a #gboolean with the result from the push + + + + + a #GstHarness + + + + a #GstEvent to push + + + + + + Transfer data from the src-#GstHarness to the main-#GstHarness. It consists +of 4 steps: +1: Make sure the src is started. (see: gst_harness_play) +2: Crank the clock (see: gst_harness_crank_single_clock_wait) +3: Pull a #GstBuffer from the src-#GstHarness (see: gst_harness_pull) +4: Push the same #GstBuffer into the main-#GstHarness (see: gst_harness_push) + +MT safe. + + a #GstFlowReturn with the result of the push + + + + + a #GstHarness + + + + + + Transfer one #GstBuffer from the main-#GstHarness to the sink-#GstHarness. +See gst_harness_push_from_src for details. + +MT safe. + + a #GstFlowReturn with the result of the push + + + + + a #GstHarness + + + + + + Pushes an #GstEvent on the #GstHarness sinkpad. + +MT safe. + + a #gboolean with the result from the push + + + + + a #GstHarness + + + + a #GstEvent to push + + + + + + Get the min latency reported by any harnessed #GstElement. + +MT safe. + + a #GstClockTime with min latency + + + + + a #GstHarness + + + + + + A convenience function to allows you to call g_object_set on a #GstElement +that are residing inside the #GstHarness, by using normal g_object_set +syntax. + +MT safe. + + + + + + a #GstHarness + + + + a #gchar with a #GstElementFactory name + + + + a #gchar with the first property name + + + + value for the first property, followed optionally by more + name/value pairs, followed by %NULL + + + + + + Setting this will make the harness block in the chain-function, and +then release when gst_harness_pull() or gst_harness_try_pull() is called. +Can be useful when wanting to control a src-element that is not implementing +gst_clock_id_wait() so it can't be controlled by the #GstTestClock, since +it otherwise would produce buffers as fast as possible. + +MT safe. + + + + + + a #GstHarness + + + + + + Sets the @GstHarness srcpad and sinkpad caps. + +MT safe. + + + + + + a #GstHarness + + + + a #GstCaps to set on the harness srcpad + + + + a #GstCaps to set on the harness sinkpad + + + + + + Sets the @GstHarness srcpad and sinkpad caps using strings. + +MT safe. + + + + + + a #GstHarness + + + + a @gchar describing a #GstCaps to set on the harness srcpad + + + + a @gchar describing a #GstCaps to set on the harness sinkpad + + + + + + When set to %TRUE, instead of placing the buffers arriving from the harnessed +#GstElement inside the sinkpads #GAsyncQueue, they are instead unreffed. + +MT safe. + + + + + + a #GstHarness + + + + a #gboolean specifying to drop outgoing buffers or not + + + + + + As a convenience, a src-harness will forward %GST_EVENT_STREAM_START, +%GST_EVENT_CAPS and %GST_EVENT_SEGMENT to the main-harness if forwarding +is enabled, and forward any sticky-events from the main-harness to +the sink-harness. It will also forward the %GST_QUERY_ALLOCATION. + +If forwarding is disabled, the user will have to either manually push +these events from the src-harness using gst_harness_src_push_event(), or +create and push them manually. While this will allow full control and +inspection of these events, for the most cases having forwarding enabled +will be sufficient when writing a test where the src-harness' main function +is providing data for the main-harness. + +Forwarding is enabled by default. + +MT safe. + + + + + + a #GstHarness + + + + a #gboolean to enable/disable forwarding + + + + + + Sets the @allocator and @params to propose when receiving an allocation +query. + +MT safe. + + + + + + a #GstHarness + + + + a #GstAllocator + + + + a #GstAllocationParams + + + + + + Sets the @GstHarness sinkpad caps. + +MT safe. + + + + + + a #GstHarness + + + + a #GstCaps to set on the harness sinkpad + + + + + + Sets the @GstHarness sinkpad caps using a string. + +MT safe. + + + + + + a #GstHarness + + + + a @gchar describing a #GstCaps to set on the harness sinkpad + + + + + + Sets the @GstHarness srcpad caps. This must be done before any buffers +can legally be pushed from the harness to the element. + +MT safe. + + + + + + a #GstHarness + + + + a #GstCaps to set on the harness srcpad + + + + + + Sets the @GstHarness srcpad caps using a string. This must be done before +any buffers can legally be pushed from the harness to the element. + +MT safe. + + + + + + a #GstHarness + + + + a @gchar describing a #GstCaps to set on the harness srcpad + + + + + + Advance the #GstTestClock to a specific time. + +MT safe. + + a @gboolean %TRUE if the time could be set. %FALSE if not. + + + + + a #GstHarness + + + + a #GstClockTime to advance the clock to + + + + + + Sets the min latency reported by #GstHarness when receiving a latency-query + + + + + + a #GstHarness + + + + a #GstClockTime specifying the latency + + + + + + Convenience that calls gst_harness_push_to_sink @pushes number of times. +Will abort the pushing if any one push fails. + +MT safe. + + a #GstFlowReturn with the result of the push + + + + + a #GstHarness + + + + a #gint with the number of calls to gst_harness_push_to_sink + + + + + + Transfer data from the src-#GstHarness to the main-#GstHarness. Similar to +gst_harness_push_from_src, this variant allows you to specify how many cranks +and how many pushes to perform. This can be useful for both moving a lot +of data at the same time, as well as cases when one crank does not equal one +buffer to push and v.v. + +MT safe. + + a #GstFlowReturn with the result of the push + + + + + a #GstHarness + + + + a #gint with the number of calls to gst_harness_crank_single_clock_wait + + + + a #gint with the number of calls to gst_harness_push + + + + + + Similar to what gst_harness_src_push does with #GstBuffers, this transfers +a #GstEvent from the src-#GstHarness to the main-#GstHarness. Note that +some #GstEvents are being transferred automagically. Look at sink_forward_pad +for details. + +MT safe. + + a #gboolean with the result of the push + + + + + a #GstHarness + + + + + + Start a custom stress-thread that will call your @callback for every +iteration allowing you to do something nasty. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GFunc that is called initially and only once + + + + a #GFunc that is called as often as possible + + + + a #gpointer with custom data to pass to the @callback function + + + + a #gulong specifying how long to sleep in (microseconds) for +each call to the @callback + + + + + + Call g_object_set with @name and @value in intervals of @sleep microseconds + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #gchar specifying a property name + + + + a #GValue to set the property to + + + + a #gulong specifying how long to sleep in (microseconds) for +each g_object_set with @name and @value + + + + + + Push a #GstBuffer in intervals of @sleep microseconds. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstCaps for the #GstBuffer + + + + a #GstSegment + + + + a #GstBuffer to push + + + + a #gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push + + + + + + Push a #GstBuffer returned by @func in intervals of @sleep microseconds. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstCaps for the #GstBuffer + + + + a #GstSegment + + + + a #GstHarnessPrepareBufferFunc function called before every iteration +to prepare / create a #GstBuffer for pushing + + + + a #gpointer with data to the #GstHarnessPrepareBufferFunc function + + + + a #GDestroyNotify that is called when thread is stopped + + + + a #gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push + + + + + + Push the @event onto the harnessed #GstElement sinkpad in intervals of +@sleep microseconds + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstEvent to push + + + + a #gulong specifying how long to sleep in (microseconds) for +each gst_event_push with @event + + + + + + Push a #GstEvent returned by @func onto the harnessed #GstElement sinkpad +in intervals of @sleep microseconds. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstHarnessPrepareEventFunc function called before every iteration +to prepare / create a #GstEvent for pushing + + + + a #gpointer with data to the #GstHarnessPrepareEventFunc function + + + + a #GDestroyNotify that is called when thread is stopped + + + + a #gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push + + + + + + Push the @event onto the harnessed #GstElement srcpad in intervals of +@sleep microseconds. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstEvent to push + + + + a #gulong specifying how long to sleep in (microseconds) for +each gst_event_push with @event + + + + + + Push a #GstEvent returned by @func onto the harnessed #GstElement srcpad +in intervals of @sleep microseconds. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstHarnessPrepareEventFunc function called before every iteration +to prepare / create a #GstEvent for pushing + + + + a #gpointer with data to the #GstHarnessPrepareEventFunc function + + + + a #GDestroyNotify that is called when thread is stopped + + + + a #gulong specifying how long to sleep in (microseconds) for +each call to gst_pad_push + + + + + + Call gst_element_request_pad in intervals of @sleep microseconds + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #GstPadTemplate + + + + a #gchar + + + + a #GstCaps + + + + a #gboolean + + + + a #gulong specifying how long to sleep in (microseconds) for +each gst_element_request_pad + + + + + + Change the state of your harnessed #GstElement from NULL to PLAYING and +back again, only pausing for @sleep microseconds every time. + +MT safe. + + a #GstHarnessThread + + + + + a #GstHarness + + + + a #gulong specifying how long to sleep in (microseconds) for +each state-change + + + + + + Pulls all pending data from the harness and returns it as a single +data slice. + + a pointer to the data, newly allocated. Free + with g_free() when no longer needed. Will return %NULL if there is no + data. + + + + + a #GstHarness + + + + the size of the data in bytes + + + + + + Pulls all pending data from the harness and returns it as a single buffer. + + the data as a buffer. Unref with gst_buffer_unref() + when no longer needed. + + + + + a #GstHarness + + + + + + Pulls all pending data from the harness and returns it as a single #GBytes. + + a pointer to the data, newly allocated. Free + with g_free() when no longer needed. + + + + + a #GstHarness + + + + + + Tears down a @GstHarness, freeing all resources allocated using it. + +MT safe. + + + + + + a #GstHarness + + + + + + Pulls a #GstBuffer from the #GAsyncQueue on the #GstHarness sinkpad. Unlike +gst_harness_pull this will not wait for any buffers if not any are present, +and return %NULL straight away. + +MT safe. + + a #GstBuffer or %NULL if no buffers are present in the #GAsyncQueue + + + + + a #GstHarness + + + + + + Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness sinkpad. +See gst_harness_try_pull for details. + +MT safe. + + a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue + + + + + a #GstHarness + + + + + + Pulls an #GstEvent from the #GAsyncQueue on the #GstHarness srcpad. +See gst_harness_try_pull for details. + +MT safe. + + a #GstEvent or %NULL if no buffers are present in the #GAsyncQueue + + + + + a #GstHarness + + + + + + The number of #GstEvents currently in the #GstHarness srcpad #GAsyncQueue + +MT safe. + + a #guint number of events in the queue + + + + + a #GstHarness + + + + + + The total number of #GstEvents that has arrived on the #GstHarness srcpad +This number includes events handled by the harness as well as events +that have already been pulled out. + +MT safe. + + a #guint number of events received + + + + + a #GstHarness + + + + + + Sets the system #GstClock on the @GstHarness #GstElement + +MT safe. + + + + + + a #GstHarness + + + + + + Sets the #GstTestClock on the #GstHarness #GstElement + +MT safe. + + + + + + a #GstHarness + + + + + + Waits for @timeout seconds until @waits number of #GstClockID waits is +registered with the #GstTestClock. Useful for writing deterministic tests, +where you want to make sure that an expected number of waits have been +reached. + +MT safe. + + a @gboolean %TRUE if the waits have been registered, %FALSE if not. +(Could be that it timed out waiting or that more waits then waits was found) + + + + + a #GstHarness + + + + a #guint describing the numbers of #GstClockID registered with +the #GstTestClock + + + + a #guint describing how many seconds to wait for @waits to be true + + + + + + Creates a new harness. Works like gst_harness_new_with_padnames(), except it +assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + + + Creates a new empty harness. Use gst_harness_add_element_full() to add +an #GstElement to it. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + Creates a new harness. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #GstElement to attach the harness to (transfer none) + + + + a #GstStaticPadTemplate describing the harness srcpad. +%NULL will not create a harness srcpad. + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. Can be a static or request +or a sometimes pad that has been added. %NULL will not get/request a sinkpad +from the element. (Like if the element is a src.) + + + + a #GstStaticPadTemplate describing the harness sinkpad. +%NULL will not create a harness sinkpad. + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad, similar to the +@element_sinkpad_name. + + + + + + Creates a new harness, parsing the @launchline and putting that in a #GstBin, +and then attches the harness to the bin. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing a gst-launch type line + + + + + + Creates a new harness. Works in the same way as gst_harness_new_full(), only +that generic padtemplates are used for the harness src and sinkpads, which +will be sufficient in most usecases. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #GstElement to attach the harness to (transfer none) + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. %NULL does not attach a +sinkpad + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad. %NULL does not attach a +srcpad + + + + + + Creates a new harness. Works like gst_harness_new_with_element(), +except you specify the factoryname of the #GstElement + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. %NULL does not attach a +sinkpad + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad. %NULL does not attach a +srcpad + + + + + + Creates a new harness, like gst_harness_new_full(), except it +assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + a #GstStaticPadTemplate describing the harness srcpad. +%NULL will not create a harness srcpad. + + + + a #GstStaticPadTemplate describing the harness sinkpad. +%NULL will not create a harness sinkpad. + + + + + + Stop the running #GstHarnessThread + +MT safe. + + + + + + a #GstHarnessThread + + + + + + + + + + + + a #GstHarness + + + + user data + + + + + + + + + + + a #GstHarness + + + + user data + + + + + + + + Opaque handle representing a GstHarness stress testing thread. + + + Opaque consistency checker handle. + + + GstTestClock is an implementation of #GstClock which has different +behaviour compared to #GstSystemClock. Time for #GstSystemClock advances +according to the system time, while time for #GstTestClock changes only +when gst_test_clock_set_time() or gst_test_clock_advance_time() are +called. #GstTestClock provides unit tests with the possibility to +precisely advance the time in a deterministic manner, independent of the +system time or any other external factors. + +## Advancing the time of a #GstTestClock + +|[<!-- language="C" --> + #include <gst/gst.h> + #include <gst/check/gsttestclock.h> + + GstClock *clock; + GstTestClock *test_clock; + + clock = gst_test_clock_new (); + test_clock = GST_TEST_CLOCK (clock); + GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + gst_test_clock_advance_time ( test_clock, 1 * GST_SECOND); + GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + g_usleep (10 * G_USEC_PER_SEC); + GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + gst_test_clock_set_time (test_clock, 42 * GST_SECOND); + GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock))); + ... +]| + +#GstClock allows for setting up single shot or periodic clock notifications +as well as waiting for these notifications synchronously (using +gst_clock_id_wait()) or asynchronously (using gst_clock_id_wait_async() or +gst_clock_id_wait_async()). This is used by many GStreamer elements, +among them #GstBaseSrc and #GstBaseSink. + +#GstTestClock keeps track of these clock notifications. By calling +gst_test_clock_wait_for_next_pending_id() or +gst_test_clock_wait_for_multiple_pending_ids() a unit tests may wait for the +next one or several clock notifications to be requested. Additionally unit +tests may release blocked waits in a controlled fashion by calling +gst_test_clock_process_next_clock_id(). This way a unit test can control the +inaccuracy (jitter) of clock notifications, since the test can decide to +release blocked waits when the clock time has advanced exactly to, or past, +the requested clock notification time. + +There are also interfaces for determining if a notification belongs to a +#GstTestClock or not, as well as getting the number of requested clock +notifications so far. + +N.B.: When a unit test waits for a certain amount of clock notifications to +be requested in gst_test_clock_wait_for_next_pending_id() or +gst_test_clock_wait_for_multiple_pending_ids() then these functions may block +for a long time. If they block forever then the expected clock notifications +were never requested from #GstTestClock, and so the assumptions in the code +of the unit test are wrong. The unit test case runner in gstcheck is +expected to catch these cases either by the default test case timeout or the +one set for the unit test by calling tcase_set_timeout\(\). + +The sample code below assumes that the element under test will delay a +buffer pushed on the source pad by some latency until it arrives on the sink +pad. Moreover it is assumed that the element will at some point call +gst_clock_id_wait() to synchronously wait for a specific time. The first +buffer sent will arrive exactly on time only delayed by the latency. The +second buffer will arrive a little late (7ms) due to simulated jitter in the +clock notification. + +## Demonstration of how to work with clock notifications and #GstTestClock + +|[<!-- language="C" --> + #include <gst/gst.h> + #include <gst/check/gstcheck.h> + #include <gst/check/gsttestclock.h> + + GstClockTime latency; + GstElement *element; + GstPad *srcpad; + GstClock *clock; + GstTestClock *test_clock; + GstBuffer buf; + GstClockID pending_id; + GstClockID processed_id; + + latency = 42 * GST_MSECOND; + element = create_element (latency, ...); + srcpad = get_source_pad (element); + + clock = gst_test_clock_new (); + test_clock = GST_TEST_CLOCK (clock); + gst_element_set_clock (element, clock); + + GST_INFO ("Set time, create and push the first buffer\n"); + gst_test_clock_set_time (test_clock, 0); + buf = create_test_buffer (gst_clock_get_time (clock), ...); + gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK); + + GST_INFO ("Block until element is waiting for a clock notification\n"); + gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + GST_INFO ("Advance to the requested time of the clock notification\n"); + gst_test_clock_advance_time (test_clock, latency); + GST_INFO ("Release the next blocking wait and make sure it is the one from element\n"); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + g_assert (processed_id == pending_id); + g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK); + gst_clock_id_unref (pending_id); + gst_clock_id_unref (processed_id); + + GST_INFO ("Validate that element produced an output buffer and check its timestamp\n"); + g_assert_cmpint (get_number_of_output_buffer (...), ==, 1); + buf = get_buffer_pushed_by_element (element, ...); + g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency); + gst_buffer_unref (buf); + GST_INFO ("Check that element does not wait for any clock notification\n"); + g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL)); + + GST_INFO ("Set time, create and push the second buffer\n"); + gst_test_clock_advance_time (test_clock, 10 * GST_SECOND); + buf = create_test_buffer (gst_clock_get_time (clock), ...); + gst_assert_cmpint (gst_pad_push (srcpad, buf), ==, GST_FLOW_OK); + + GST_INFO ("Block until element is waiting for a new clock notification\n"); + (gst_test_clock_wait_for_next_pending_id (test_clock, &pending_id); + GST_INFO ("Advance past 7ms beyond the requested time of the clock notification\n"); + gst_test_clock_advance_time (test_clock, latency + 7 * GST_MSECOND); + GST_INFO ("Release the next blocking wait and make sure it is the one from element\n"); + processed_id = gst_test_clock_process_next_clock_id (test_clock); + g_assert (processed_id == pending_id); + g_assert_cmpint (GST_CLOCK_ENTRY_STATUS (processed_id), ==, GST_CLOCK_OK); + gst_clock_id_unref (pending_id); + gst_clock_id_unref (processed_id); + + GST_INFO ("Validate that element produced an output buffer and check its timestamp\n"); + g_assert_cmpint (get_number_of_output_buffer (...), ==, 1); + buf = get_buffer_pushed_by_element (element, ...); + g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, + 10 * GST_SECOND + latency + 7 * GST_MSECOND); + gst_buffer_unref (buf); + GST_INFO ("Check that element does not wait for any clock notification\n"); + g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL)); + ... +]| + +Since #GstTestClock is only supposed to be used in unit tests it calls +g_assert(), g_assert_cmpint() or g_assert_cmpuint() to validate all function +arguments. This will highlight any issues with the unit test code itself. + + Creates a new test clock with its time set to zero. + +MT safe. + + a #GstTestClock cast to #GstClock. + + + + + Creates a new test clock with its time set to the specified time. + +MT safe. + + a #GstTestClock cast to #GstClock. + + + + + a #GstClockTime set to the desired start time of the clock. + + + + + + Finds the latest time inside the list. + +MT safe. + + + + + + List + of of pending #GstClockIDs + + + + + + + + Advances the time of the @test_clock by the amount given by @delta. The +time of @test_clock is monotonically increasing, therefore providing a +@delta which is negative or zero is a programming error. + +MT safe. + + + + + + a #GstTestClock for which to increase the time + + + + a positive #GstClockTimeDiff to be added to the time of the clock + + + + + + A "crank" consists of three steps: +1: Wait for a #GstClockID to be registered with the #GstTestClock. +2: Advance the #GstTestClock to the time the #GstClockID is waiting for. +3: Release the #GstClockID wait. +A "crank" can be though of as the notion of +manually driving the clock forward to its next logical step. + + %TRUE if the crank was successful, %FALSE otherwise. + +MT safe. + + + + + #GstTestClock to crank + + + + + + Retrieve the requested time for the next pending clock notification. + +MT safe. + + a #GstClockTime set to the time of the next pending clock +notification. If no clock notifications have been requested +%GST_CLOCK_TIME_NONE will be returned. + + + + + a #GstTestClock to fetch the next clock notification time for + + + + + + Checks whether @test_clock was requested to provide the clock notification +given by @id. + +MT safe. + + %TRUE if the clock has been asked to provide the given clock +notification, %FALSE otherwise. + + + + + a #GstTestClock to ask if it provided the notification + + + + a #GstClockID clock notification + + + + + + Determine the number of pending clock notifications that have been +requested from the @test_clock. + +MT safe. + + the number of pending clock notifications. + + + + + a #GstTestClock for which to count notifications + + + + + + Determines if the @pending_id is the next clock notification scheduled to +be triggered given the current time of the @test_clock. + +MT safe. + + %TRUE if @pending_id is the next clock notification to be +triggered, %FALSE otherwise. + + + + + a #GstTestClock to check the clock notifications for + + + + a #GstClockID clock +notification to look for + + + + + + Processes and releases the pending IDs in the list. + +MT safe. + + + + + + #GstTestClock for which to process the pending IDs + + + + List + of pending #GstClockIDs + + + + + + + + MT safe. + + a #GstClockID containing the next pending clock +notification. + + + + + a #GstTestClock for which to retrieve the next pending clock +notification + + + + + + Sets the time of @test_clock to the time given by @new_time. The time of +@test_clock is monotonically increasing, therefore providing a @new_time +which is earlier or equal to the time of the clock as given by +gst_clock_get_time() is a programming error. + +MT safe. + + + + + + a #GstTestClock of which to set the time + + + + a #GstClockTime later than that returned by gst_clock_get_time() + + + + + + Blocks until at least @count clock notifications have been requested from +@test_clock. There is no timeout for this wait, see the main description of +#GstTestClock. + +MT safe. + + + + + + #GstTestClock for which to await having enough pending clock + + + + the number of pending clock notifications to wait for + + + + Address + of a #GList pointer variable to store the list of pending #GstClockIDs + that expired, or %NULL + + + + + + + + Waits until a clock notification is requested from @test_clock. There is no +timeout for this wait, see the main description of #GstTestClock. A reference +to the pending clock notification is stored in @pending_id. + +MT safe. + + + + + + #GstTestClock for which to get the pending clock notification + + + + #GstClockID +with information about the pending clock notification + + + + + + Blocks until at least @count clock notifications have been requested from +@test_clock. There is no timeout for this wait, see the main description of +#GstTestClock. + use gst_test_clock_wait_for_multiple_pending_ids() instead. + + + + + + #GstTestClock for which to await having enough pending clock + + + + the number of pending clock notifications to wait for + + + + + + + + + When a #GstTestClock is constructed it will have a certain start time set. +If the clock was created using gst_test_clock_new_with_start_time() then +this property contains the value of the @start_time argument. If +gst_test_clock_new() was called the clock started at time zero, and thus +this property contains the value 0. + + + + + + + + + + + The class of a #GstTestClock, which has no virtual methods to override. + + the parent class structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sets up a data probe on the given pad which will raise assertions if the +data flow is inconsistent. + + %TRUE if the pad was added + + + + + The #GstStreamConsistency handle + + + + The #GstPad on which the dataflow will be checked. + + + + + + Frees the allocated data and probes associated with @consist. + + + + + + The #GstStreamConsistency to free. + + + + + + Sets up a data probe on the given pad which will raise assertions if the +data flow is inconsistent. + + A #GstStreamConsistency structure used to track data flow. + + + + + The #GstPad on which the dataflow will be checked. + + + + + + Reset the stream checker's internal variables. + + + + + + The #GstStreamConsistency to reset. + + + + + + Creates a new harness. Works like gst_harness_new_with_padnames(), except it +assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + + + Creates a new empty harness. Use gst_harness_add_element_full() to add +an #GstElement to it. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + Creates a new harness. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #GstElement to attach the harness to (transfer none) + + + + a #GstStaticPadTemplate describing the harness srcpad. +%NULL will not create a harness srcpad. + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. Can be a static or request +or a sometimes pad that has been added. %NULL will not get/request a sinkpad +from the element. (Like if the element is a src.) + + + + a #GstStaticPadTemplate describing the harness sinkpad. +%NULL will not create a harness sinkpad. + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad, similar to the +@element_sinkpad_name. + + + + + + Creates a new harness, parsing the @launchline and putting that in a #GstBin, +and then attches the harness to the bin. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing a gst-launch type line + + + + + + Creates a new harness. Works in the same way as gst_harness_new_full(), only +that generic padtemplates are used for the harness src and sinkpads, which +will be sufficient in most usecases. + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #GstElement to attach the harness to (transfer none) + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. %NULL does not attach a +sinkpad + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad. %NULL does not attach a +srcpad + + + + + + Creates a new harness. Works like gst_harness_new_with_element(), +except you specify the factoryname of the #GstElement + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + a #gchar with the name of the element +sinkpad that is then linked to the harness srcpad. %NULL does not attach a +sinkpad + + + + a #gchar with the name of the element +srcpad that is then linked to the harness sinkpad. %NULL does not attach a +srcpad + + + + + + Creates a new harness, like gst_harness_new_full(), except it +assumes the #GstElement sinkpad is named "sink" and srcpad is named "src" + +MT safe. + + a #GstHarness, or %NULL if the harness could +not be created + + + + + a #gchar describing the #GstElement name + + + + a #GstStaticPadTemplate describing the harness srcpad. +%NULL will not create a harness srcpad. + + + + a #GstStaticPadTemplate describing the harness sinkpad. +%NULL will not create a harness sinkpad. + + + + + + Stop the running #GstHarnessThread + +MT safe. + + + + + + a #GstHarnessThread + + + + + + diff --git a/gstreamer-check/src/auto/mod.rs b/gstreamer-check/src/auto/mod.rs new file mode 100644 index 000000000..fbae6e9a0 --- /dev/null +++ b/gstreamer-check/src/auto/mod.rs @@ -0,0 +1,12 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +mod test_clock; +pub use self::test_clock::TestClock; +pub use self::test_clock::TestClockExt; + +#[doc(hidden)] +pub mod traits { + pub use super::TestClockExt; +} diff --git a/gstreamer-check/src/auto/test_clock.rs b/gstreamer-check/src/auto/test_clock.rs new file mode 100644 index 000000000..ba38dcad0 --- /dev/null +++ b/gstreamer-check/src/auto/test_clock.rs @@ -0,0 +1,193 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +use ffi; +use glib; +use glib::StaticType; +use glib::Value; +use glib::object::Downcast; +use glib::object::IsA; +use glib::signal::SignalHandlerId; +use glib::signal::connect; +use glib::translate::*; +use glib_ffi; +use gobject_ffi; +use gst; +use gst_ffi; +use std::boxed::Box as Box_; +use std::mem; +use std::mem::transmute; +use std::ptr; + +glib_wrapper! { + pub struct TestClock(Object): [ + gst::Clock => gst_ffi::GstClock, + gst::Object => gst_ffi::GstObject, + ]; + + match fn { + get_type => || ffi::gst_test_clock_get_type(), + } +} + +impl TestClock { + pub fn new() -> TestClock { + assert_initialized_main_thread!(); + unsafe { + gst::Clock::from_glib_full(ffi::gst_test_clock_new()).downcast_unchecked() + } + } + + pub fn new_with_start_time(start_time: gst::ClockTime) -> TestClock { + assert_initialized_main_thread!(); + unsafe { + gst::Clock::from_glib_full(ffi::gst_test_clock_new_with_start_time(start_time.to_glib())).downcast_unchecked() + } + } + + //pub fn id_list_get_latest_time(pending_list: /*Ignored*/&[&gst::ClockID]) -> gst::ClockTime { + // unsafe { TODO: call ffi::gst_test_clock_id_list_get_latest_time() } + //} +} + +impl Default for TestClock { + fn default() -> Self { + Self::new() + } +} + +unsafe impl Send for TestClock {} +unsafe impl Sync for TestClock {} + +pub trait TestClockExt { + fn advance_time(&self, delta: gst::ClockTimeDiff); + + fn crank(&self) -> bool; + + fn get_next_entry_time(&self) -> gst::ClockTime; + + //fn has_id(&self, id: /*Ignored*/gst::ClockID) -> bool; + + fn peek_id_count(&self) -> u32; + + //fn peek_next_pending_id(&self, pending_id: /*Ignored*/&mut gst::ClockID) -> bool; + + //fn process_id_list(&self, pending_list: /*Ignored*/&[&gst::ClockID]) -> u32; + + //fn process_next_clock_id(&self) -> /*Ignored*/Option; + + fn set_time(&self, new_time: gst::ClockTime); + + //fn wait_for_multiple_pending_ids(&self, count: u32, pending_list: /*Unimplemented*/Vec); + + //fn wait_for_next_pending_id(&self, pending_id: /*Ignored*/&mut gst::ClockID); + + fn wait_for_pending_id_count(&self, count: u32); + + fn get_property_clock_type(&self) -> gst::ClockType; + + fn set_property_clock_type(&self, clock_type: gst::ClockType); + + fn get_property_start_time(&self) -> u64; + + fn connect_property_clock_type_notify(&self, f: F) -> SignalHandlerId; +} + +impl + IsA> TestClockExt for O { + fn advance_time(&self, delta: gst::ClockTimeDiff) { + unsafe { + ffi::gst_test_clock_advance_time(self.to_glib_none().0, delta); + } + } + + fn crank(&self) -> bool { + unsafe { + from_glib(ffi::gst_test_clock_crank(self.to_glib_none().0)) + } + } + + fn get_next_entry_time(&self) -> gst::ClockTime { + unsafe { + from_glib(ffi::gst_test_clock_get_next_entry_time(self.to_glib_none().0)) + } + } + + //fn has_id(&self, id: /*Ignored*/gst::ClockID) -> bool { + // unsafe { TODO: call ffi::gst_test_clock_has_id() } + //} + + fn peek_id_count(&self) -> u32 { + unsafe { + ffi::gst_test_clock_peek_id_count(self.to_glib_none().0) + } + } + + //fn peek_next_pending_id(&self, pending_id: /*Ignored*/&mut gst::ClockID) -> bool { + // unsafe { TODO: call ffi::gst_test_clock_peek_next_pending_id() } + //} + + //fn process_id_list(&self, pending_list: /*Ignored*/&[&gst::ClockID]) -> u32 { + // unsafe { TODO: call ffi::gst_test_clock_process_id_list() } + //} + + //fn process_next_clock_id(&self) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_test_clock_process_next_clock_id() } + //} + + fn set_time(&self, new_time: gst::ClockTime) { + unsafe { + ffi::gst_test_clock_set_time(self.to_glib_none().0, new_time.to_glib()); + } + } + + //fn wait_for_multiple_pending_ids(&self, count: u32, pending_list: /*Unimplemented*/Vec) { + // unsafe { TODO: call ffi::gst_test_clock_wait_for_multiple_pending_ids() } + //} + + //fn wait_for_next_pending_id(&self, pending_id: /*Ignored*/&mut gst::ClockID) { + // unsafe { TODO: call ffi::gst_test_clock_wait_for_next_pending_id() } + //} + + fn wait_for_pending_id_count(&self, count: u32) { + unsafe { + ffi::gst_test_clock_wait_for_pending_id_count(self.to_glib_none().0, count); + } + } + + fn get_property_clock_type(&self) -> gst::ClockType { + unsafe { + let mut value = Value::from_type(::static_type()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "clock-type".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn set_property_clock_type(&self, clock_type: gst::ClockType) { + unsafe { + gobject_ffi::g_object_set_property(self.to_glib_none().0, "clock-type".to_glib_none().0, Value::from(&clock_type).to_glib_none().0); + } + } + + fn get_property_start_time(&self) -> u64 { + unsafe { + let mut value = Value::from_type(::static_type()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "start-time".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn connect_property_clock_type_notify(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::clock-type", + transmute(notify_clock_type_trampoline:: as usize), Box_::into_raw(f) as *mut _) + } + } +} + +unsafe extern "C" fn notify_clock_type_trampoline

(this: *mut ffi::GstTestClock, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA { + let f: &&(Fn(&P) + Send + Sync + 'static) = transmute(f); + f(&TestClock::from_glib_borrow(this).downcast_unchecked()) +} diff --git a/gstreamer-check/src/auto/versions.txt b/gstreamer-check/src/auto/versions.txt new file mode 100644 index 000000000..3ae6fb524 --- /dev/null +++ b/gstreamer-check/src/auto/versions.txt @@ -0,0 +1,2 @@ +Generated by gir (https://github.com/gtk-rs/gir @ 82cdb44) +from gir-files (https://github.com/gtk-rs/gir-files @ ???) diff --git a/gstreamer-check/src/harness.rs b/gstreamer-check/src/harness.rs new file mode 100644 index 000000000..26a86c8c8 --- /dev/null +++ b/gstreamer-check/src/harness.rs @@ -0,0 +1,646 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +use ffi; +#[cfg(any(feature = "v1_14", feature = "dox"))] +use glib; +use glib::object::IsA; +use glib::translate::*; +use glib_ffi; +use gst; +use std::mem; +use std::ptr; +use TestClock; + +glib_wrapper! { + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Harness(Boxed); + + match fn { + copy => |ptr| ffi::gst_harness_copy(mut_override(ptr)), + free => |ptr| ffi::gst_harness_free(ptr), + } +} + +impl Harness { + pub fn add_element_full< + 'a, + 'b, + 'c, + 'd, + P: IsA, + Q: Into>, + R: Into>, + S: Into>, + T: Into>, + >( + &mut self, + element: &P, + hsrc: Q, + element_sinkpad_name: R, + hsink: S, + element_srcpad_name: T, + ) { + let hsrc = hsrc.into(); + let element_sinkpad_name = element_sinkpad_name.into(); + let element_sinkpad_name = element_sinkpad_name.to_glib_none(); + let hsink = hsink.into(); + let element_srcpad_name = element_srcpad_name.into(); + let element_srcpad_name = element_srcpad_name.to_glib_none(); + unsafe { + ffi::gst_harness_add_element_full( + self.to_glib_none_mut().0, + element.to_glib_none().0, + hsrc.to_glib_none_mut().0, + element_sinkpad_name.0, + hsink.to_glib_none_mut().0, + element_srcpad_name.0, + ); + } + } + + pub fn add_element_sink_pad>(&mut self, sinkpad: &P) { + unsafe { + ffi::gst_harness_add_element_sink_pad( + self.to_glib_none_mut().0, + sinkpad.to_glib_none().0, + ); + } + } + + pub fn add_element_src_pad>(&mut self, srcpad: &P) { + unsafe { + ffi::gst_harness_add_element_src_pad( + self.to_glib_none_mut().0, + srcpad.to_glib_none().0, + ); + } + } + + pub fn add_parse(&mut self, launchline: &str) { + unsafe { + ffi::gst_harness_add_parse(self.to_glib_none_mut().0, launchline.to_glib_none().0); + } + } + + //pub fn add_probe(&mut self, element_name: &str, pad_name: &str, mask: /*Ignored*/gst::PadProbeType, callback: /*Unknown conversion*//*Unimplemented*/PadProbeCallback, destroy_data: /*Unknown conversion*//*Unimplemented*/DestroyNotify) { + // unsafe { TODO: call ffi::gst_harness_add_probe() } + //} + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn add_propose_allocation_meta<'a, P: Into>>( + &mut self, + api: glib::types::Type, + params: P, + ) { + let params = params.into(); + let params = params.to_glib_none(); + unsafe { + ffi::gst_harness_add_propose_allocation_meta( + self.to_glib_none_mut().0, + api.to_glib(), + params.0, + ); + } + } + + pub fn add_sink(&mut self, sink_element_name: &str) { + unsafe { + ffi::gst_harness_add_sink( + self.to_glib_none_mut().0, + sink_element_name.to_glib_none().0, + ); + } + } + + pub fn add_sink_harness(&mut self, sink_harness: &mut Harness) { + unsafe { + ffi::gst_harness_add_sink_harness( + self.to_glib_none_mut().0, + sink_harness.to_glib_full(), + ); + } + } + + pub fn add_sink_parse(&mut self, launchline: &str) { + unsafe { + ffi::gst_harness_add_sink_parse(self.to_glib_none_mut().0, launchline.to_glib_none().0); + } + } + + pub fn add_src(&mut self, src_element_name: &str, has_clock_wait: bool) { + unsafe { + ffi::gst_harness_add_src( + self.to_glib_none_mut().0, + src_element_name.to_glib_none().0, + has_clock_wait.to_glib(), + ); + } + } + + pub fn add_src_harness(&mut self, src_harness: &mut Harness, has_clock_wait: bool) { + unsafe { + ffi::gst_harness_add_src_harness( + self.to_glib_none_mut().0, + src_harness.to_glib_full(), + has_clock_wait.to_glib(), + ); + } + } + + pub fn add_src_parse(&mut self, launchline: &str, has_clock_wait: bool) { + unsafe { + ffi::gst_harness_add_src_parse( + self.to_glib_none_mut().0, + launchline.to_glib_none().0, + has_clock_wait.to_glib(), + ); + } + } + + pub fn buffers_in_queue(&mut self) -> u32 { + unsafe { ffi::gst_harness_buffers_in_queue(self.to_glib_none_mut().0) } + } + + pub fn buffers_received(&mut self) -> u32 { + unsafe { ffi::gst_harness_buffers_received(self.to_glib_none_mut().0) } + } + + pub fn crank_multiple_clock_waits(&mut self, waits: u32) -> bool { + unsafe { + from_glib(ffi::gst_harness_crank_multiple_clock_waits( + self.to_glib_none_mut().0, + waits, + )) + } + } + + pub fn crank_single_clock_wait(&mut self) -> bool { + unsafe { + from_glib(ffi::gst_harness_crank_single_clock_wait( + self.to_glib_none_mut().0, + )) + } + } + + pub fn create_buffer(&mut self, size: usize) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_create_buffer( + self.to_glib_none_mut().0, + size, + )) + } + } + + pub fn dump_to_file(&mut self, filename: &str) { + unsafe { + ffi::gst_harness_dump_to_file(self.to_glib_none_mut().0, filename.to_glib_none().0); + } + } + + pub fn events_in_queue(&mut self) -> u32 { + unsafe { ffi::gst_harness_events_in_queue(self.to_glib_none_mut().0) } + } + + pub fn events_received(&mut self) -> u32 { + unsafe { ffi::gst_harness_events_received(self.to_glib_none_mut().0) } + } + + pub fn find_element(&mut self, element_name: &str) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_find_element( + self.to_glib_none_mut().0, + element_name.to_glib_none().0, + )) + } + } + + //pub fn get(&mut self, element_name: &str, first_property_name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) { + // unsafe { TODO: call ffi::gst_harness_get() } + //} + + //pub fn get_allocator(&mut self, allocator: /*Ignored*/gst::Allocator, params: /*Ignored*/gst::AllocationParams) { + // unsafe { TODO: call ffi::gst_harness_get_allocator() } + //} + + pub fn get_last_pushed_timestamp(&mut self) -> gst::ClockTime { + unsafe { ffi::gst_harness_get_last_pushed_timestamp(self.to_glib_none_mut().0) } + } + + pub fn get_testclock(&mut self) -> Option { + unsafe { from_glib_full(ffi::gst_harness_get_testclock(self.to_glib_none_mut().0)) } + } + + pub fn play(&mut self) { + unsafe { + ffi::gst_harness_play(self.to_glib_none_mut().0); + } + } + + pub fn pull(&mut self) -> Option { + unsafe { from_glib_full(ffi::gst_harness_pull(self.to_glib_none_mut().0)) } + } + + pub fn pull_event(&mut self) -> Option { + unsafe { from_glib_full(ffi::gst_harness_pull_event(self.to_glib_none_mut().0)) } + } + + pub fn pull_upstream_event(&mut self) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_pull_upstream_event( + self.to_glib_none_mut().0, + )) + } + } + + pub fn push(&mut self, buffer: &mut gst::Buffer) -> gst::FlowReturn { + unsafe { + from_glib(ffi::gst_harness_push( + self.to_glib_none_mut().0, + buffer.to_glib_full(), + )) + } + } + + pub fn push_and_pull(&mut self, buffer: &mut gst::Buffer) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_push_and_pull( + self.to_glib_none_mut().0, + buffer.to_glib_full(), + )) + } + } + + pub fn push_event(&mut self, event: &mut gst::Event) -> bool { + unsafe { + from_glib(ffi::gst_harness_push_event( + self.to_glib_none_mut().0, + event.to_glib_none_mut().0, + )) + } + } + + pub fn push_from_src(&mut self) -> gst::FlowReturn { + unsafe { from_glib(ffi::gst_harness_push_from_src(self.to_glib_none_mut().0)) } + } + + pub fn push_to_sink(&mut self) -> gst::FlowReturn { + unsafe { from_glib(ffi::gst_harness_push_to_sink(self.to_glib_none_mut().0)) } + } + + pub fn push_upstream_event(&mut self, event: &mut gst::Event) -> bool { + unsafe { + from_glib(ffi::gst_harness_push_upstream_event( + self.to_glib_none_mut().0, + event.to_glib_none_mut().0, + )) + } + } + + pub fn query_latency(&mut self) -> gst::ClockTime { + unsafe { ffi::gst_harness_query_latency(self.to_glib_none_mut().0) } + } + + //pub fn set(&mut self, element_name: &str, first_property_name: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) { + // unsafe { TODO: call ffi::gst_harness_set() } + //} + + pub fn set_blocking_push_mode(&mut self) { + unsafe { + ffi::gst_harness_set_blocking_push_mode(self.to_glib_none_mut().0); + } + } + + pub fn set_caps(&mut self, in_: &mut gst::Caps, out: &mut gst::Caps) { + unsafe { + ffi::gst_harness_set_caps( + self.to_glib_none_mut().0, + in_.to_glib_full(), + out.to_glib_full(), + ); + } + } + + pub fn set_caps_str(&mut self, in_: &str, out: &str) { + unsafe { + ffi::gst_harness_set_caps_str( + self.to_glib_none_mut().0, + in_.to_glib_none().0, + out.to_glib_none().0, + ); + } + } + + pub fn set_drop_buffers(&mut self, drop_buffers: bool) { + unsafe { + ffi::gst_harness_set_drop_buffers(self.to_glib_none_mut().0, drop_buffers.to_glib()); + } + } + + pub fn set_forwarding(&mut self, forwarding: bool) { + unsafe { + ffi::gst_harness_set_forwarding(self.to_glib_none_mut().0, forwarding.to_glib()); + } + } + + //pub fn set_propose_allocator<'a, 'b, P: Into>, Q: Into>>(&mut self, allocator: P, params: Q) { + // unsafe { TODO: call ffi::gst_harness_set_propose_allocator() } + //} + + pub fn set_sink_caps(&mut self, caps: &mut gst::Caps) { + unsafe { + ffi::gst_harness_set_sink_caps(self.to_glib_none_mut().0, caps.to_glib_full()); + } + } + + pub fn set_sink_caps_str(&mut self, str: &str) { + unsafe { + ffi::gst_harness_set_sink_caps_str(self.to_glib_none_mut().0, str.to_glib_none().0); + } + } + + pub fn set_src_caps(&mut self, caps: &mut gst::Caps) { + unsafe { + ffi::gst_harness_set_src_caps(self.to_glib_none_mut().0, caps.to_glib_full()); + } + } + + pub fn set_src_caps_str(&mut self, str: &str) { + unsafe { + ffi::gst_harness_set_src_caps_str(self.to_glib_none_mut().0, str.to_glib_none().0); + } + } + + pub fn set_time(&mut self, time: gst::ClockTime) -> bool { + unsafe { from_glib(ffi::gst_harness_set_time(self.to_glib_none_mut().0, time)) } + } + + pub fn set_upstream_latency(&mut self, latency: gst::ClockTime) { + unsafe { + ffi::gst_harness_set_upstream_latency(self.to_glib_none_mut().0, latency); + } + } + + pub fn sink_push_many(&mut self, pushes: i32) -> gst::FlowReturn { + unsafe { + from_glib(ffi::gst_harness_sink_push_many( + self.to_glib_none_mut().0, + pushes, + )) + } + } + + pub fn src_crank_and_push_many(&mut self, cranks: i32, pushes: i32) -> gst::FlowReturn { + unsafe { + from_glib(ffi::gst_harness_src_crank_and_push_many( + self.to_glib_none_mut().0, + cranks, + pushes, + )) + } + } + + pub fn src_push_event(&mut self) -> bool { + unsafe { from_glib(ffi::gst_harness_src_push_event(self.to_glib_none_mut().0)) } + } + + //pub fn stress_custom_start<'a, P: Into>, Q: Into>>(&mut self, init: P, callback: /*Unknown conversion*//*Unimplemented*/Func, data: Q, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_custom_start() } + //} + + //pub fn stress_property_start_full(&mut self, name: &str, value: /*Ignored*/&glib::Value, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_property_start_full() } + //} + + //pub fn stress_push_buffer_start_full(&mut self, caps: &mut gst::Caps, segment: /*Ignored*/&gst::Segment, buf: &mut gst::Buffer, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_buffer_start_full() } + //} + + //pub fn stress_push_buffer_with_cb_start_full>>(&mut self, caps: &mut gst::Caps, segment: /*Ignored*/&gst::Segment, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareBufferFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_buffer_with_cb_start_full() } + //} + + //pub fn stress_push_event_start_full(&mut self, event: &mut gst::Event, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_event_start_full() } + //} + + //pub fn stress_push_event_with_cb_start_full>>(&mut self, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareEventFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_event_with_cb_start_full() } + //} + + //pub fn stress_push_upstream_event_start_full(&mut self, event: &mut gst::Event, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_upstream_event_start_full() } + //} + + //pub fn stress_push_upstream_event_with_cb_start_full>>(&mut self, func: /*Unknown conversion*//*Unimplemented*/HarnessPrepareEventFunc, data: P, notify: /*Unknown conversion*//*Unimplemented*/DestroyNotify, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_push_upstream_event_with_cb_start_full() } + //} + + //pub fn stress_requestpad_start_full(&mut self, templ: /*Ignored*/&gst::PadTemplate, name: &str, caps: &mut gst::Caps, release: bool, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_requestpad_start_full() } + //} + + //pub fn stress_statechange_start_full(&mut self, sleep: libc::c_ulong) -> /*Ignored*/Option { + // unsafe { TODO: call ffi::gst_harness_stress_statechange_start_full() } + //} + + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn take_all_data(&mut self) -> (u8, usize) { + unsafe { + let mut size = mem::uninitialized(); + let ret = ffi::gst_harness_take_all_data(self.to_glib_none_mut().0, &mut size); + (ret, size) + } + } + + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn take_all_data_as_buffer(&mut self) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_take_all_data_as_buffer( + self.to_glib_none_mut().0, + )) + } + } + + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn take_all_data_as_bytes(&mut self) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_take_all_data_as_bytes( + self.to_glib_none_mut().0, + )) + } + } + + pub fn teardown(&mut self) { + unsafe { + ffi::gst_harness_teardown(self.to_glib_none_mut().0); + } + } + + pub fn try_pull(&mut self) -> Option { + unsafe { from_glib_full(ffi::gst_harness_try_pull(self.to_glib_none_mut().0)) } + } + + pub fn try_pull_event(&mut self) -> Option { + unsafe { from_glib_full(ffi::gst_harness_try_pull_event(self.to_glib_none_mut().0)) } + } + + pub fn try_pull_upstream_event(&mut self) -> Option { + unsafe { + from_glib_full(ffi::gst_harness_try_pull_upstream_event( + self.to_glib_none_mut().0, + )) + } + } + + pub fn upstream_events_in_queue(&mut self) -> u32 { + unsafe { ffi::gst_harness_upstream_events_in_queue(self.to_glib_none_mut().0) } + } + + pub fn upstream_events_received(&mut self) -> u32 { + unsafe { ffi::gst_harness_upstream_events_received(self.to_glib_none_mut().0) } + } + + pub fn use_systemclock(&mut self) { + unsafe { + ffi::gst_harness_use_systemclock(self.to_glib_none_mut().0); + } + } + + pub fn use_testclock(&mut self) { + unsafe { + ffi::gst_harness_use_testclock(self.to_glib_none_mut().0); + } + } + + pub fn wait_for_clock_id_waits(&mut self, waits: u32, timeout: u32) -> bool { + unsafe { + from_glib(ffi::gst_harness_wait_for_clock_id_waits( + self.to_glib_none_mut().0, + waits, + timeout, + )) + } + } + + pub fn new(element_name: &str) -> Option { + assert_initialized_main_thread!(); + unsafe { from_glib_full(ffi::gst_harness_new(element_name.to_glib_none().0)) } + } + + pub fn new_empty() -> Option { + assert_initialized_main_thread!(); + unsafe { from_glib_full(ffi::gst_harness_new_empty()) } + } + + pub fn new_full< + 'a, + 'b, + 'c, + 'd, + P: IsA, + Q: Into>, + R: Into>, + S: Into>, + T: Into>, + >( + element: &P, + hsrc: Q, + element_sinkpad_name: R, + hsink: S, + element_srcpad_name: T, + ) -> Option { + assert_initialized_main_thread!(); + let hsrc = hsrc.into(); + let element_sinkpad_name = element_sinkpad_name.into(); + let element_sinkpad_name = element_sinkpad_name.to_glib_none(); + let hsink = hsink.into(); + let element_srcpad_name = element_srcpad_name.into(); + let element_srcpad_name = element_srcpad_name.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_harness_new_full( + element.to_glib_none().0, + hsrc.to_glib_none_mut().0, + element_sinkpad_name.0, + hsink.to_glib_none_mut().0, + element_srcpad_name.0, + )) + } + } + + pub fn new_parse(launchline: &str) -> Option { + assert_initialized_main_thread!(); + unsafe { from_glib_full(ffi::gst_harness_new_parse(launchline.to_glib_none().0)) } + } + + pub fn new_with_element< + 'a, + 'b, + P: IsA, + Q: Into>, + R: Into>, + >( + element: &P, + element_sinkpad_name: Q, + element_srcpad_name: R, + ) -> Option { + assert_initialized_main_thread!(); + let element_sinkpad_name = element_sinkpad_name.into(); + let element_sinkpad_name = element_sinkpad_name.to_glib_none(); + let element_srcpad_name = element_srcpad_name.into(); + let element_srcpad_name = element_srcpad_name.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_harness_new_with_element( + element.to_glib_none().0, + element_sinkpad_name.0, + element_srcpad_name.0, + )) + } + } + + pub fn new_with_padnames<'a, 'b, P: Into>, Q: Into>>( + element_name: &str, + element_sinkpad_name: P, + element_srcpad_name: Q, + ) -> Option { + assert_initialized_main_thread!(); + let element_sinkpad_name = element_sinkpad_name.into(); + let element_sinkpad_name = element_sinkpad_name.to_glib_none(); + let element_srcpad_name = element_srcpad_name.into(); + let element_srcpad_name = element_srcpad_name.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_harness_new_with_padnames( + element_name.to_glib_none().0, + element_sinkpad_name.0, + element_srcpad_name.0, + )) + } + } + + pub fn new_with_templates< + 'a, + 'b, + P: Into>, + Q: Into>, + >( + element_name: &str, + hsrc: P, + hsink: Q, + ) -> Option { + assert_initialized_main_thread!(); + let hsrc = hsrc.into(); + let hsink = hsink.into(); + unsafe { + from_glib_full(ffi::gst_harness_new_with_templates( + element_name.to_glib_none().0, + hsrc.to_glib_none_mut().0, + hsink.to_glib_none_mut().0, + )) + } + } + + //pub fn stress_thread_stop(t: /*Ignored*/&mut HarnessThread) -> u32 { + // unsafe { TODO: call ffi::gst_harness_stress_thread_stop() } + //} +}