mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
pad: add pull mode probes
Allow probes to inspect the offset and size from a probe in pull mode and allow the probe to modify the buffer. Update design doc a little.
This commit is contained in:
parent
ba3028aeeb
commit
ce09010267
3 changed files with 102 additions and 61 deletions
|
@ -45,20 +45,22 @@ Overview
|
|||
|
||||
typedef enum
|
||||
{
|
||||
GST_PAD_PROBE_TYPE_INVALID = 0,
|
||||
GST_PAD_PROBE_TYPE_INVALID = 0,
|
||||
|
||||
/* flags to control blocking */
|
||||
GST_PAD_PROBE_TYPE_IDLE = (1 << 0),
|
||||
GST_PAD_PROBE_TYPE_BLOCK = (1 << 1),
|
||||
GST_PAD_PROBE_TYPE_IDLE = (1 << 0),
|
||||
GST_PAD_PROBE_TYPE_BLOCK = (1 << 1),
|
||||
|
||||
/* flags to select datatypes */
|
||||
GST_PAD_PROBE_TYPE_BUFFER = (1 << 2),
|
||||
GST_PAD_PROBE_TYPE_BUFFER_LIST = (1 << 3),
|
||||
GST_PAD_PROBE_TYPE_EVENT = (1 << 4),
|
||||
GST_PAD_PROBE_TYPE_BUFFER = (1 << 2),
|
||||
GST_PAD_PROBE_TYPE_BUFFER_LIST = (1 << 3),
|
||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM = (1 << 4),
|
||||
GST_PAD_PROBE_TYPE_EVENT_UPSTREAM = (1 << 5),
|
||||
|
||||
/* flags to select scheduling mode */
|
||||
GST_PAD_PROBE_TYPE_PUSH = (1 << 5),
|
||||
GST_PAD_PROBE_TYPE_PULL = (1 << 6),
|
||||
GST_PAD_PROBE_TYPE_PUSH = (1 << 6),
|
||||
GST_PAD_PROBE_TYPE_PULL = (1 << 7),
|
||||
|
||||
} GstPadProbeType;
|
||||
|
||||
When adding a probe with the IDLE or BLOCK flag, the probe will become a
|
||||
|
@ -71,14 +73,13 @@ Overview
|
|||
|
||||
The probe callback is defined as:
|
||||
|
||||
GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeType type,
|
||||
gpointer type_data,
|
||||
GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info,
|
||||
gpointer user_data);
|
||||
|
||||
The executing probe type is passed as an argument and is guaranteed to match
|
||||
the mask that was used to register the callback. type_data contains type
|
||||
specific data, which is usually the data item that is blocked or NULL when
|
||||
no data item is present.
|
||||
A probe info structure is passed as an argument and its type is guaranteed
|
||||
to match the mask that was used to register the callback. The data item in the
|
||||
info contains type specific data, which is usually the data item that is blocked
|
||||
or NULL when no data item is present.
|
||||
|
||||
The probe can return any of the following return values:
|
||||
|
||||
|
@ -111,8 +112,8 @@ Blocking probes
|
|||
thread.
|
||||
|
||||
The IDLE probe in useful to perform dynamic linking, it allows to wait for for
|
||||
a safe moment when an unlink/link operation can be done. Since the event is a
|
||||
blocking event, it will also make sure that the pad stays idle until the probe
|
||||
a safe moment when an unlink/link operation can be done. Since the probe is a
|
||||
blocking probe, it will also make sure that the pad stays idle until the probe
|
||||
is removed.
|
||||
|
||||
When the BLOCK flag is set, the probe callback will be called when new data
|
||||
|
@ -135,7 +136,7 @@ Non-Blocking probes
|
|||
Push dataflow
|
||||
-------------
|
||||
|
||||
All probes have the GST_PAD_PROBE_TYPE_PUSH flag set in the callbacks.
|
||||
Push probes have the GST_PAD_PROBE_TYPE_PUSH flag set in the callbacks.
|
||||
|
||||
In push based scheduling, the blocking probe is called first with the data item.
|
||||
Then the data probes are called before the peer pad chain or event function is
|
||||
|
@ -144,13 +145,13 @@ called.
|
|||
The data probes are called before the peer pad is checked. This allows for
|
||||
linking the pad in either the BLOCK or DATA probes on the pad.
|
||||
|
||||
Before the peerpad chain or event function is called, the peer pad data probes
|
||||
are called.
|
||||
Before the peerpad chain or event function is called, the peer pad block and
|
||||
data probes are called.
|
||||
|
||||
Finally, the IDLE probe is called on the pad after the data was sent to the
|
||||
peer pad.
|
||||
|
||||
The push dataflow probe behavior is the same for buffers and biderectional events.
|
||||
The push dataflow probe behavior is the same for buffers and bidirectional events.
|
||||
|
||||
|
||||
pad peerpad
|
||||
|
@ -191,19 +192,20 @@ The push dataflow probe behavior is the same for buffers and biderectional event
|
|||
Pull dataflow
|
||||
-------------
|
||||
|
||||
All probes have the GST_PAD_PROBE_TYPE_PULL flag set in the callbacks.
|
||||
Pull probes have the GST_PAD_PROBE_TYPE_PULL flag set in the callbacks.
|
||||
|
||||
The gst_pad_pull_range() call will first trigger the BLOCK probes without a DATA
|
||||
item. This allows the pad to be linked before the peer pad is resolved.
|
||||
item. This allows the pad to be linked before the peer pad is resolved. It also
|
||||
allows the callback to set a data item in the probe info.
|
||||
|
||||
After the getrange function is called on the peer pad and there is a data item,
|
||||
the DATA probes are called.
|
||||
After the blocking probe and the getrange function is called on the peer pad
|
||||
and there is a data item, the DATA probes are called.
|
||||
|
||||
When control returns to the sinkpad, the IDLE callbacks are called. The IDLE
|
||||
callback is called without a data item so that it will also be called when there
|
||||
was an error.
|
||||
|
||||
It there is a valid DATA item, the DATA probes are called for the item.
|
||||
If there is a valid DATA item, the DATA probes are called for the item.
|
||||
|
||||
|
||||
srcpad sinkpad
|
||||
|
|
84
gst/gstpad.c
84
gst/gstpad.c
|
@ -3400,20 +3400,40 @@ no_match:
|
|||
}
|
||||
}
|
||||
|
||||
#define PROBE_ND_FULL(pad,mask,label,defaultval) \
|
||||
#define PROBE_PRE_PULL(pad,mask,data,offs,size,label,probed,defaultval) \
|
||||
G_STMT_START { \
|
||||
if (G_UNLIKELY (pad->num_probes)) { \
|
||||
GstPadProbeInfo info = { mask, NULL }; \
|
||||
/* we start with passing NULL as the data item */ \
|
||||
GstPadProbeInfo info = { mask, NULL, offs, size }; \
|
||||
ret = do_probe_callbacks (pad, &info, defaultval); \
|
||||
/* store the possibly updated data item */ \
|
||||
data = GST_PAD_PROBE_INFO_DATA (&info); \
|
||||
/* if something went wrong, exit */ \
|
||||
if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK)) \
|
||||
goto label; \
|
||||
/* otherwise check if the probe retured data */ \
|
||||
if (G_UNLIKELY (data != NULL)) \
|
||||
goto probed; \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
|
||||
/* a probe that does not take or return any data */
|
||||
#define PROBE_NO_DATA(pad,mask,label,defaultval) \
|
||||
G_STMT_START { \
|
||||
if (G_UNLIKELY (pad->num_probes)) { \
|
||||
/* pass NULL as the data item */ \
|
||||
GstPadProbeInfo info = { mask, NULL, 0, 0 }; \
|
||||
ret = do_probe_callbacks (pad, &info, defaultval); \
|
||||
if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK)) \
|
||||
goto label; \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
#define PROBE_FULL(pad,mask,data,label,defaultval) \
|
||||
#define PROBE_FULL(pad,mask,data,offs,size,label,defaultval) \
|
||||
G_STMT_START { \
|
||||
if (G_UNLIKELY (pad->num_probes)) { \
|
||||
GstPadProbeInfo info = { mask, data }; \
|
||||
GstPadProbeInfo info = { mask, data, offs, size }; \
|
||||
ret = do_probe_callbacks (pad, &info, defaultval); \
|
||||
data = GST_PAD_PROBE_INFO_DATA (&info); \
|
||||
if (G_UNLIKELY (ret != defaultval && ret != GST_FLOW_OK)) \
|
||||
|
@ -3421,10 +3441,10 @@ no_match:
|
|||
} \
|
||||
} G_STMT_END
|
||||
|
||||
#define PROBE(pad,mask,data,label) \
|
||||
PROBE_FULL(pad, mask, data, label, GST_FLOW_OK);
|
||||
#define PROBE_ND(pad,mask,label) \
|
||||
PROBE_ND_FULL(pad, mask, label, GST_FLOW_OK);
|
||||
#define PROBE_PUSH(pad,mask,data,label) \
|
||||
PROBE_FULL(pad, mask, data, -1, -1, label, GST_FLOW_OK);
|
||||
#define PROBE_PULL(pad,mask,data,offs,size,label) \
|
||||
PROBE_FULL(pad, mask, data, offs, size, label, GST_FLOW_OK);
|
||||
|
||||
static GstFlowReturn
|
||||
do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info,
|
||||
|
@ -3637,9 +3657,9 @@ gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data)
|
|||
goto events_error;
|
||||
}
|
||||
|
||||
PROBE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
|
||||
|
||||
PROBE (pad, type, data, probe_stopped);
|
||||
PROBE_PUSH (pad, type, data, probe_stopped);
|
||||
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
|
@ -3844,10 +3864,10 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data)
|
|||
goto flushing;
|
||||
|
||||
/* do block probes */
|
||||
PROBE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped);
|
||||
|
||||
/* do post-blocking probes */
|
||||
PROBE (pad, type, data, probe_stopped);
|
||||
PROBE_PUSH (pad, type, data, probe_stopped);
|
||||
|
||||
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
|
||||
goto not_linked;
|
||||
|
@ -3865,7 +3885,7 @@ gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data)
|
|||
pad->priv->using--;
|
||||
if (pad->priv->using == 0) {
|
||||
/* pad is not active anymore, trigger idle callbacks */
|
||||
PROBE_ND_FULL (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
|
||||
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
|
||||
probe_stopped, ret);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
@ -3991,8 +4011,10 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
|
|||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushing;
|
||||
|
||||
PROBE_ND (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
|
||||
probe_stopped);
|
||||
/* when one of the probes returns a buffer, probed_data will be called and we
|
||||
* skip calling the getrange function */
|
||||
PROBE_PRE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
|
||||
*buffer, offset, size, probe_stopped, probed_data, GST_FLOW_OK);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL))
|
||||
|
@ -4010,8 +4032,9 @@ gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
|
|||
|
||||
/* can only fire the signal if we have a valid buffer */
|
||||
GST_OBJECT_LOCK (pad);
|
||||
PROBE (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER, *buffer,
|
||||
probe_stopped_unref);
|
||||
probed_data:
|
||||
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
|
||||
*buffer, offset, size, probe_stopped_unref);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
GST_PAD_STREAM_UNLOCK (pad);
|
||||
|
@ -4139,8 +4162,10 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
|
|||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushing;
|
||||
|
||||
PROBE_ND (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
|
||||
pre_probe_stopped);
|
||||
/* when one of the probes returns a buffer, probed_data will be called and we
|
||||
* skip calling the peer getrange function */
|
||||
PROBE_PRE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
|
||||
*buffer, offset, size, pre_probe_stopped, probed_data, GST_FLOW_OK);
|
||||
|
||||
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
|
||||
goto not_linked;
|
||||
|
@ -4157,15 +4182,16 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
|
|||
pad->priv->using--;
|
||||
if (pad->priv->using == 0) {
|
||||
/* pad is not active anymore, trigger idle callbacks */
|
||||
PROBE_ND (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE,
|
||||
post_probe_stopped);
|
||||
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE,
|
||||
post_probe_stopped, ret);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
||||
goto pull_range_failed;
|
||||
|
||||
PROBE (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER, buffer,
|
||||
post_probe_stopped);
|
||||
probed_data:
|
||||
PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
|
||||
*buffer, offset, size, post_probe_stopped);
|
||||
|
||||
needs_events = GST_PAD_NEEDS_EVENTS (pad);
|
||||
if (G_UNLIKELY (needs_events)) {
|
||||
|
@ -4360,7 +4386,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
|||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushed;
|
||||
|
||||
PROBE (pad, type | GST_PAD_PROBE_TYPE_PUSH |
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
|
||||
GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
|
||||
|
||||
break;
|
||||
|
@ -4368,7 +4394,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
|||
}
|
||||
|
||||
/* send probes after modifying the events above */
|
||||
PROBE (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
|
||||
|
||||
/* now check the peer pad */
|
||||
if (peerpad == NULL)
|
||||
|
@ -4395,8 +4421,8 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
|||
pad->priv->using--;
|
||||
if (pad->priv->using == 0) {
|
||||
/* pad is not active anymore, trigger idle callbacks */
|
||||
PROBE_ND (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
|
||||
probe_stopped);
|
||||
PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
|
||||
probe_stopped, GST_FLOW_OK);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
|
@ -4574,11 +4600,11 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
|
|||
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
|
||||
goto flushing;
|
||||
|
||||
PROBE (pad,
|
||||
PROBE_PUSH (pad,
|
||||
type | GST_PAD_PROBE_TYPE_PUSH |
|
||||
GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
|
||||
|
||||
PROBE (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
|
||||
PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
27
gst/gstpad.h
27
gst/gstpad.h
|
@ -213,9 +213,9 @@ typedef enum {
|
|||
|
||||
/**
|
||||
* GstPadActivateMode:
|
||||
* @GST_PAD_ACTIVATE_NONE: Pad will not handle dataflow
|
||||
* @GST_PAD_ACTIVATE_PUSH: Pad handles dataflow in downstream push mode
|
||||
* @GST_PAD_ACTIVATE_PULL: Pad handles dataflow in upstream pull mode
|
||||
* @GST_PAD_ACTIVATE_NONE: Pad will not handle dataflow
|
||||
* @GST_PAD_ACTIVATE_PUSH: Pad handles dataflow in downstream push mode
|
||||
* @GST_PAD_ACTIVATE_PULL: Pad handles dataflow in upstream pull mode
|
||||
*
|
||||
* The status of a GstPad. After activating a pad, which usually happens when the
|
||||
* parent element goes from READY to PAUSED, the GstPadActivateMode defines if the
|
||||
|
@ -531,7 +531,12 @@ typedef enum
|
|||
/**
|
||||
* GstPadProbeInfo:
|
||||
* @type: the current probe type
|
||||
* @data: type specific data
|
||||
* @data: type specific data, check the @type field to know the datatype.
|
||||
* This field can be NULL.
|
||||
* @offset: offset of pull probe, this field is valid when @type contains
|
||||
* #GST_PAD_PROBE_TYPE_PULL
|
||||
* @size: size of pull probe, this field is valid when @type contains
|
||||
* #GST_PAD_PROBE_TYPE_PULL
|
||||
*
|
||||
* Info passed in the #GstPadProbeCallback.
|
||||
*/
|
||||
|
@ -539,6 +544,8 @@ typedef struct
|
|||
{
|
||||
GstPadProbeType type;
|
||||
gpointer data;
|
||||
guint64 offset;
|
||||
guint size;
|
||||
} GstPadProbeInfo;
|
||||
|
||||
#define GST_PAD_PROBE_INFO_TYPE(d) ((d)->type)
|
||||
|
@ -548,6 +555,9 @@ typedef struct
|
|||
#define GST_PAD_PROBE_INFO_BUFFER_LIST(d) GST_BUFFER_LIST_CAST(GST_PAD_PROBE_INFO_DATA(d))
|
||||
#define GST_PAD_PROBE_INFO_EVENT(d) GST_EVENT_CAST(GST_PAD_PROBE_INFO_DATA(d))
|
||||
|
||||
#define GST_PAD_PROBE_INFO_OFFSET(d) ((d)->offset)
|
||||
#define GST_PAD_PROBE_INFO_SIZE(d) ((d)->size)
|
||||
|
||||
/**
|
||||
* GstPadProbeCallback
|
||||
* @pad: the #GstPad that is blocked
|
||||
|
@ -556,9 +566,11 @@ typedef struct
|
|||
*
|
||||
* Callback used by gst_pad_add_probe(). Gets called to notify about the current
|
||||
* blocking type.
|
||||
*
|
||||
* The callback is allowed to modify the data pointer in @info.
|
||||
*/
|
||||
typedef GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info,
|
||||
gpointer user_data);
|
||||
typedef GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* GstPadStickyEventsForeachFunction:
|
||||
|
@ -570,7 +582,8 @@ typedef GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad,
|
|||
*
|
||||
* Returns: GST_FLOW_OK if the iteration should continue
|
||||
*/
|
||||
typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent *event, gpointer user_data);
|
||||
typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEvent *event,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* GstPadFlags:
|
||||
|
|
Loading…
Reference in a new issue