mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
pad: add per-pad offsets
When linking pads and when copying a segment event from the sourc pad to the sinkpad, apply the src and sinkpad offsets to the segment base. Make sure that we only modify the event stored on the sinkpad and never the one on the source pad. When changing the pad offset, perform the segment copy with the updated offsets. When pushing a segment event, apply the srcpad offset before sending the event to the peer pad. This part is missing the adjustment of the segment event on the sinkpad, which is for a later patch.
This commit is contained in:
parent
c8340e7762
commit
e8b8c4aaa6
1 changed files with 129 additions and 19 deletions
138
gst/gstpad.c
138
gst/gstpad.c
|
@ -379,26 +379,55 @@ clear_events (PadEvent events[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called when elements link. The sticky events from the srcpad are
|
/* The sticky event with @idx from the srcpad is copied to the
|
||||||
* copied to the sinkpad (when different) and the inactive flag is set,
|
* sinkpad (when different) and the inactive flag is set.
|
||||||
* this will make sure that we send the event to the sinkpad event
|
* This function applies the pad offsets in case of segment events.
|
||||||
* function when the next buffer of event arrives. */
|
* This will make sure that we send the event to the sinkpad event
|
||||||
|
* function when the next buffer of event arrives.
|
||||||
|
* Should be called with the OBJECT lock of both pads */
|
||||||
static gboolean
|
static gboolean
|
||||||
replace_events (PadEvent srcev[], PadEvent sinkev[])
|
replace_event (GstPad * srcpad, GstPad * sinkpad, guint idx)
|
||||||
{
|
{
|
||||||
guint i;
|
PadEvent *srcev, *sinkev;
|
||||||
|
GstEvent *event;
|
||||||
gboolean inactive = FALSE;
|
gboolean inactive = FALSE;
|
||||||
|
|
||||||
for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
|
srcev = &srcpad->priv->events[idx];
|
||||||
if (srcev[i].event != sinkev[i].event) {
|
|
||||||
gst_event_replace (&sinkev[i].event, srcev[i].event);
|
if ((event = srcev->event)) {
|
||||||
sinkev[i].active = FALSE;
|
sinkev = &sinkpad->priv->events[idx];
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_SEGMENT:
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
gint64 offset;
|
||||||
|
|
||||||
|
offset = srcpad->offset + sinkpad->offset;
|
||||||
|
if (offset != 0) {
|
||||||
|
gst_event_copy_segment (event, &segment);
|
||||||
|
/* adjust the base time. FIXME, check negative times, try to tweak the
|
||||||
|
* start to do clipping on negative times */
|
||||||
|
segment.base += offset;
|
||||||
|
/* make a new event from the updated segment */
|
||||||
|
event = gst_event_new_segment (&segment);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sinkev->event != event) {
|
||||||
|
/* replace when different */
|
||||||
|
gst_event_replace (&sinkev->event, event);
|
||||||
|
sinkev->active = FALSE;
|
||||||
inactive = TRUE;
|
inactive = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inactive;
|
return inactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* should be called with the OBJECT_LOCK */
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
get_pad_caps (GstPad * pad)
|
get_pad_caps (GstPad * pad)
|
||||||
{
|
{
|
||||||
|
@ -2047,6 +2076,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
{
|
{
|
||||||
GstPadLinkReturn result;
|
GstPadLinkReturn result;
|
||||||
GstElement *parent;
|
GstElement *parent;
|
||||||
|
guint i;
|
||||||
|
gboolean inactive;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
|
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
|
||||||
g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
|
g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
|
||||||
|
@ -2078,7 +2109,12 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
|
|
||||||
/* make sure we push the events from the source to this new peer, for this we
|
/* make sure we push the events from the source to this new peer, for this we
|
||||||
* copy the events on the sinkpad and mark EVENTS_PENDING */
|
* copy the events on the sinkpad and mark EVENTS_PENDING */
|
||||||
if (replace_events (srcpad->priv->events, sinkpad->priv->events))
|
inactive = FALSE;
|
||||||
|
for (i = 0; i < GST_EVENT_MAX_STICKY; i++)
|
||||||
|
inactive |= replace_event (srcpad, sinkpad, i);
|
||||||
|
|
||||||
|
/* we had some new inactive events, set our flag */
|
||||||
|
if (inactive)
|
||||||
GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_NEED_EVENTS);
|
GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_NEED_EVENTS);
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (sinkpad);
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
|
@ -3590,7 +3626,8 @@ flushing:
|
||||||
* gst_pad_get_offset:
|
* gst_pad_get_offset:
|
||||||
* @pad: a #GstPad
|
* @pad: a #GstPad
|
||||||
*
|
*
|
||||||
* Get the offset applied to the running time of @pad.
|
* Get the offset applied to the running time of @pad. @pad has to be a source
|
||||||
|
* pad.
|
||||||
*
|
*
|
||||||
* Returns: the offset.
|
* Returns: the offset.
|
||||||
*/
|
*/
|
||||||
|
@ -3618,10 +3655,56 @@ gst_pad_get_offset (GstPad * pad)
|
||||||
void
|
void
|
||||||
gst_pad_set_offset (GstPad * pad, gint64 offset)
|
gst_pad_set_offset (GstPad * pad, gint64 offset)
|
||||||
{
|
{
|
||||||
|
guint idx;
|
||||||
|
GstPad *peer;
|
||||||
|
GstPad *tmp = NULL;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_PAD (pad));
|
g_return_if_fail (GST_IS_PAD (pad));
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
GST_OBJECT_LOCK (pad);
|
||||||
|
/* if nothing changed, do nothing */
|
||||||
|
if (pad->offset == offset)
|
||||||
|
goto done;
|
||||||
|
|
||||||
pad->offset = offset;
|
pad->offset = offset;
|
||||||
|
|
||||||
|
/* if no peer, we just updated the offset */
|
||||||
|
if ((peer = GST_PAD_PEER (pad)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* switch pads around when dealing with a sinkpad */
|
||||||
|
if (GST_PAD_IS_SINK (pad)) {
|
||||||
|
/* ref the peer so it doesn't go away when we release the lock */
|
||||||
|
tmp = gst_object_ref (peer);
|
||||||
|
/* make sure we get the peer (the srcpad) */
|
||||||
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
|
/* swap pads */
|
||||||
|
peer = pad;
|
||||||
|
pad = tmp;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (pad);
|
||||||
|
/* check if the pad didn't get relinked */
|
||||||
|
if (GST_PAD_PEER (pad) != peer)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* we can release the ref now */
|
||||||
|
gst_object_unref (peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the index of the segment event in the array */
|
||||||
|
idx = GST_EVENT_STICKY_IDX_TYPE (GST_EVENT_SEGMENT);
|
||||||
|
|
||||||
|
/* lock order is srcpad >> sinkpad */
|
||||||
|
GST_OBJECT_LOCK (peer);
|
||||||
|
/* take the current segment event, adjust it and then place
|
||||||
|
* it on the sinkpad. events on the srcpad are always active. */
|
||||||
|
if (replace_event (pad, peer, idx))
|
||||||
|
GST_OBJECT_FLAG_SET (peer, GST_PAD_NEED_EVENTS);
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (peer);
|
||||||
|
|
||||||
|
done:
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4580,6 +4663,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
||||||
{
|
{
|
||||||
GstPad *peerpad;
|
GstPad *peerpad;
|
||||||
gboolean result;
|
gboolean result;
|
||||||
|
gint64 offset;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||||
g_return_val_if_fail (event != NULL, FALSE);
|
g_return_val_if_fail (event != NULL, FALSE);
|
||||||
|
@ -4652,16 +4736,42 @@ gst_pad_push_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
if ((peerpad = GST_PAD_PEER (pad)))
|
if ((peerpad = GST_PAD_PEER (pad)))
|
||||||
gst_object_ref (peerpad);
|
gst_object_ref (peerpad);
|
||||||
|
|
||||||
|
offset = pad->offset;
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
/* backwards compatibility mode for caps */
|
/* backwards compatibility mode for caps */
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
gst_event_parse_caps (event, &caps);
|
gst_event_parse_caps (event, &caps);
|
||||||
/* FIXME, this is awkward because we don't check flushing here which means
|
/* FIXME, this is awkward because we don't check flushing here which means
|
||||||
* that we can call the setcaps functions on flushing pads, this is not
|
* that we can call the setcaps functions on flushing pads, this is not
|
||||||
* quite what we want */
|
* quite what we want, otoh, this code should just go away and elements
|
||||||
|
* that set caps on their sinkpad should just setup stuff themselves. */
|
||||||
gst_pad_call_setcaps (pad, caps);
|
gst_pad_call_setcaps (pad, caps);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GST_EVENT_SEGMENT:
|
||||||
|
{
|
||||||
|
/* check if we need to adjust the segment */
|
||||||
|
if (offset != 0 && peerpad != NULL) {
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
|
/* copy segment values */
|
||||||
|
gst_event_copy_segment (event, &segment);
|
||||||
|
gst_event_unref (event);
|
||||||
|
|
||||||
|
/* adjust and make a new event with the offset applied */
|
||||||
|
segment.base += offset;
|
||||||
|
event = gst_event_new_segment (&segment);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now check the peer pad */
|
/* now check the peer pad */
|
||||||
|
|
Loading…
Reference in a new issue