static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event);
static GstPad *gst_adder_request_new_pad (GstElement * element,
- GstPadTemplate * temp, const gchar * unused);
+ GstPadTemplate * temp, const gchar * unused, const GstCaps * caps);
static void gst_adder_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_adder_change_state (GstElement * element,
* if we have filtercaps set, use those to constrain the target caps.
*/
static GstCaps *
-gst_adder_sink_getcaps (GstPad * pad)
+gst_adder_sink_getcaps (GstPad * pad, GstCaps * filter)
{
GstAdder *adder;
GstCaps *result, *peercaps, *sinkcaps, *filter_caps;
GST_OBJECT_LOCK (adder);
/* take filter */
- if ((filter_caps = adder->filter_caps))
- gst_caps_ref (filter_caps);
+ if ((filter_caps = adder->filter_caps)) {
+ if (filter)
+ filter_caps =
+ gst_caps_intersect_full (filter, filter_caps,
+ GST_CAPS_INTERSECT_FIRST);
+ else
+ gst_caps_ref (filter_caps);
+ } else {
+ filter_caps = gst_caps_ref (filter);
+ }
GST_OBJECT_UNLOCK (adder);
+ if (filter_caps && gst_caps_is_empty (filter_caps)) {
+ GST_WARNING_OBJECT (pad, "Empty filter caps");
+ return filter_caps;
+ }
+
/* get the downstream possible caps */
- peercaps = gst_pad_peer_get_caps (adder->srcpad);
+ peercaps = gst_pad_peer_get_caps (adder->srcpad, filter_caps);
/* get the allowed caps on this sinkpad */
sinkcaps = gst_pad_get_current_caps (pad);
if (sinkcaps == NULL) {
- sinkcaps = (GstCaps *) gst_pad_get_pad_template_caps (pad);
- if (sinkcaps)
- gst_caps_ref (sinkcaps);
- else
+ sinkcaps = gst_pad_get_pad_template_caps (pad);
+ if (!sinkcaps)
sinkcaps = gst_caps_new_any ();
}
if (peercaps) {
- /* restrict with filter-caps if any */
- if (filter_caps) {
- GST_DEBUG_OBJECT (adder, "filtering peer caps");
- result = gst_caps_intersect (peercaps, filter_caps);
- gst_caps_unref (peercaps);
- peercaps = result;
- }
/* if the peer has caps, intersect */
GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
- result = gst_caps_intersect (peercaps, sinkcaps);
+ result =
+ gst_caps_intersect_full (peercaps, sinkcaps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (peercaps);
gst_caps_unref (sinkcaps);
} else {
/* restrict with filter-caps if any */
if (filter_caps) {
GST_DEBUG_OBJECT (adder, "no peer caps, using filtered sinkcaps");
- result = gst_caps_intersect (sinkcaps, filter_caps);
+ result =
+ gst_caps_intersect_full (filter_caps, sinkcaps,
+ GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (sinkcaps);
} else {
GST_DEBUG_OBJECT (adder, "no peer caps, using sinkcaps");
switch (format) {
case GST_FORMAT_TIME:
/* FIXME, bring to stream time, might be tricky */
- gst_query_set_position (query, format, adder->timestamp);
+ gst_query_set_position (query, format, adder->segment.position);
res = TRUE;
break;
case GST_FORMAT_DEFAULT:
case GST_EVENT_SEEK:
{
GstSeekFlags flags;
+ gdouble rate;
GstSeekType curtype, endtype;
gint64 cur, end;
gboolean flush;
/* parse the seek parameters */
- gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype,
+ gst_event_parse_seek (event, &rate, NULL, &flags, &curtype,
&cur, &endtype, &end);
if ((curtype != GST_SEEK_TYPE_NONE) && (curtype != GST_SEEK_TYPE_SET)) {
* segment. After we have the lock, no collect function is running and no
* new collect function will be called for as long as we're flushing. */
GST_OBJECT_LOCK (adder->collect);
+ adder->segment.rate = rate;
if (curtype == GST_SEEK_TYPE_SET)
- adder->segment_start = cur;
+ adder->segment.start = cur;
else
- adder->segment_start = 0;
+ adder->segment.start = 0;
if (endtype == GST_SEEK_TYPE_SET)
- adder->segment_end = end;
+ adder->segment.stop = end;
else
- adder->segment_end = GST_CLOCK_TIME_NONE;
+ adder->segment.stop = GST_CLOCK_TIME_NONE;
/* make sure we push a new segment, to inform about new basetime
* see FIXME in gst_adder_collected() */
adder->segment_pending = TRUE;
static GstPad *
gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
- const gchar * unused)
+ const gchar * unused, const GstCaps * caps)
{
gchar *name;
GstAdder *adder;
adder = GST_ADDER (element);
/* increment pad counter */
+#if GLIB_CHECK_VERSION(2,29,5)
+ padcount = g_atomic_int_add (&adder->padcount, 1);
+#else
padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1);
+#endif
name = g_strdup_printf ("sink%d", padcount);
newpad = gst_pad_new_from_template (templ, name);
* event. We also adjust offset & timestamp acordingly.
* This basically ignores all newsegments sent by upstream.
*/
- event = gst_event_new_new_segment (FALSE, adder->segment_rate,
- 1.0, GST_FORMAT_TIME, adder->segment_start, adder->segment_end,
- adder->segment_start);
- if (adder->segment_rate > 0.0) {
- adder->timestamp = adder->segment_start;
+ event = gst_event_new_segment (&adder->segment);
+
+ if (adder->segment.rate > 0.0) {
+ adder->segment.position = adder->segment.start;
} else {
- adder->timestamp = adder->segment_end;
+ adder->segment.position = adder->segment.stop;
}
- adder->offset = gst_util_uint64_scale (adder->timestamp,
+ adder->offset = gst_util_uint64_scale (adder->segment.position,
adder->rate, GST_SECOND);
GST_INFO_OBJECT (adder, "seg_start %" G_GUINT64_FORMAT ", seg_end %"
- G_GUINT64_FORMAT, adder->segment_start, adder->segment_end);
+ G_GUINT64_FORMAT, adder->segment.start, adder->segment.stop);
GST_INFO_OBJECT (adder, "timestamp %" G_GINT64_FORMAT ",new offset %"
- G_GINT64_FORMAT, adder->timestamp, adder->offset);
+ G_GINT64_FORMAT, adder->segment.position, adder->offset);
if (event) {
if (!gst_pad_push_event (adder->srcpad, event)) {
} else {
GST_WARNING_OBJECT (adder->srcpad, "Creating new segment event for "
"start:%" G_GINT64_FORMAT " end:%" G_GINT64_FORMAT " failed",
- adder->segment_start, adder->segment_end);
+ adder->segment.start, adder->segment.stop);
}
}
/* for the next timestamp, use the sample counter, which will
* never accumulate rounding errors */
- if (adder->segment_rate > 0.0) {
+ if (adder->segment.rate > 0.0) {
next_offset = adder->offset + outsize / adder->bps;
} else {
next_offset = adder->offset - outsize / adder->bps;
/* set timestamps on the output buffer */
- if (adder->segment_rate > 0.0) {
- GST_BUFFER_TIMESTAMP (outbuf) = adder->timestamp;
+ if (adder->segment.rate > 0.0) {
+ GST_BUFFER_TIMESTAMP (outbuf) = adder->segment.position;
GST_BUFFER_OFFSET (outbuf) = adder->offset;
GST_BUFFER_OFFSET_END (outbuf) = next_offset;
- GST_BUFFER_DURATION (outbuf) = next_timestamp - adder->timestamp;
+ GST_BUFFER_DURATION (outbuf) = next_timestamp - adder->segment.position;
} else {
GST_BUFFER_TIMESTAMP (outbuf) = next_timestamp;
GST_BUFFER_OFFSET (outbuf) = next_offset;
GST_BUFFER_OFFSET_END (outbuf) = adder->offset;
- GST_BUFFER_DURATION (outbuf) = adder->timestamp - next_timestamp;
+ GST_BUFFER_DURATION (outbuf) = adder->segment.position - next_timestamp;
}
adder->offset = next_offset;
- adder->timestamp = next_timestamp;
+ adder->segment.position = next_timestamp;
/* send it out */
GST_LOG_OBJECT (adder, "pushing outbuf %p, timestamp %" GST_TIME_FORMAT
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- adder->timestamp = 0;
+ adder->segment.position = 0;
adder->offset = 0;
adder->flush_stop_pending = FALSE;
adder->segment_pending = TRUE;
- adder->segment_start = 0;
- adder->segment_end = GST_CLOCK_TIME_NONE;
- adder->segment_rate = 1.0;
- gst_segment_init (&adder->segment, GST_FORMAT_UNDEFINED);
+ gst_segment_init (&adder->segment, GST_FORMAT_TIME);
gst_collect_pads_start (adder->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: