diff --git a/ext/gl/gstglbasemixer.c b/ext/gl/gstglbasemixer.c index 6e6e9493e0..317d339ed4 100644 --- a/ext/gl/gstglbasemixer.c +++ b/ext/gl/gstglbasemixer.c @@ -108,11 +108,14 @@ gst_gl_base_mixer_pad_set_property (GObject * object, guint prop_id, } static gboolean -_negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) +_negotiated_caps (GstAggregator * agg, GstCaps * caps) { - GstGLBaseMixer *mix = GST_GL_BASE_MIXER (vagg); + GstGLBaseMixer *mix = GST_GL_BASE_MIXER (agg); - return gst_gl_base_mixer_do_bufferpool (mix, caps); + if (!gst_gl_base_mixer_do_bufferpool (mix, caps)) + return FALSE; + + return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps); } static gboolean @@ -324,9 +327,6 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass) { GObjectClass *gobject_class; GstElementClass *element_class; - - GstVideoAggregatorClass *videoaggregator_class = - (GstVideoAggregatorClass *) klass; GstAggregatorClass *agg_class = (GstAggregatorClass *) klass; GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glmixer", 0, "opengl mixer"); @@ -350,8 +350,7 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass) agg_class->src_activate = gst_gl_base_mixer_src_activate_mode; agg_class->stop = gst_gl_base_mixer_stop; agg_class->start = gst_gl_base_mixer_start; - - videoaggregator_class->negotiated_caps = _negotiated_caps; + agg_class->negotiated_src_caps = _negotiated_caps; klass->propose_allocation = _default_propose_allocation; diff --git a/ext/gl/gstglmixer.c b/ext/gl/gstglmixer.c index b8f4da0267..d2ce49da8a 100644 --- a/ext/gl/gstglmixer.c +++ b/ext/gl/gstglmixer.c @@ -96,16 +96,16 @@ gst_gl_mixer_pad_set_property (GObject * object, guint prop_id, } static gboolean -_negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) +_negotiated_caps (GstAggregator * agg, GstCaps * caps) { - GstGLMixer *mix = GST_GL_MIXER (vagg); + GstGLMixer *mix = GST_GL_MIXER (agg); gboolean ret; mix->priv->negotiated = TRUE; gst_caps_replace (&mix->out_caps, caps); - ret = GST_VIDEO_AGGREGATOR_CLASS (parent_class)->negotiated_caps (vagg, caps); + ret = GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps); return ret; } @@ -215,29 +215,6 @@ gst_gl_mixer_pad_sink_acceptcaps (GstPad * pad, GstGLMixer * mix, return ret; } -/* copies the given caps */ -static GstCaps * -_update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) -{ - GstCaps *tmp; - guint i, n; - - if (filter) { - tmp = gst_caps_intersect (caps, filter); - tmp = gst_caps_make_writable (tmp); - } else { - tmp = gst_caps_copy (caps); - } - - n = gst_caps_get_size (tmp); - for (i = 0; i < n; i++) { - gst_caps_set_features (tmp, i, - gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); - } - - return tmp; -} - static GstCaps * gst_gl_mixer_pad_sink_getcaps (GstPad * pad, GstGLMixer * mix, GstCaps * filter) { @@ -391,11 +368,10 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass) agg_class->src_query = gst_gl_mixer_src_query; agg_class->stop = gst_gl_mixer_stop; agg_class->start = gst_gl_mixer_start; + agg_class->negotiated_src_caps = _negotiated_caps; videoaggregator_class->aggregate_frames = gst_gl_mixer_aggregate_frames; videoaggregator_class->get_output_buffer = gst_gl_mixer_get_output_buffer; - videoaggregator_class->negotiated_caps = _negotiated_caps; - videoaggregator_class->update_caps = _update_caps; videoaggregator_class->find_best_format = _find_best_format; mix_class->propose_allocation = gst_gl_mixer_propose_allocation; diff --git a/ext/gl/gstglstereomix.c b/ext/gl/gstglstereomix.c index 78a2934fad..9e42b23f67 100644 --- a/ext/gl/gstglstereomix.c +++ b/ext/gl/gstglstereomix.c @@ -81,10 +81,8 @@ gst_gl_stereo_mix_pad_init (GstGLStereoMixPad * pad) #define gst_gl_stereo_mix_parent_class parent_class G_DEFINE_TYPE (GstGLStereoMix, gst_gl_stereo_mix, GST_TYPE_GL_MIXER); -static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps, - GstCaps * filter); -static gboolean _negotiated_caps (GstVideoAggregator * videoaggregator, - GstCaps * caps); +static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps); +static gboolean _negotiated_caps (GstAggregator * aggregator, GstCaps * caps); gboolean gst_gl_stereo_mix_make_output (GstGLStereoMix * mix); static gboolean gst_gl_stereo_mix_process_frames (GstGLStereoMix * mixer); @@ -188,10 +186,10 @@ gst_gl_stereo_mix_class_init (GstGLStereoMixClass * klass) agg_class->stop = gst_gl_stereo_mix_stop; agg_class->start = gst_gl_stereo_mix_start; agg_class->src_query = gst_gl_stereo_mix_src_query; + agg_class->negotiated_src_caps = _negotiated_caps; videoaggregator_class->aggregate_frames = gst_gl_stereo_mix_aggregate_frames; videoaggregator_class->update_caps = _update_caps; - videoaggregator_class->negotiated_caps = _negotiated_caps; videoaggregator_class->get_output_buffer = gst_gl_stereo_mix_get_output_buffer; @@ -470,7 +468,7 @@ get_converted_caps (GstGLStereoMix * mix, GstCaps * caps) /* Return the possible output caps based on inputs and downstream prefs */ static GstCaps * -_update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) +_update_caps (GstVideoAggregator * vagg, GstCaps * caps) { GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg); GList *l; @@ -563,16 +561,16 @@ _update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) /* Called after videoaggregator fixates our caps */ static gboolean -_negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) +_negotiated_caps (GstAggregator * agg, GstCaps * caps) { + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg); GstCaps *in_caps; GST_LOG_OBJECT (mix, "Configured output caps %" GST_PTR_FORMAT, caps); - if (GST_VIDEO_AGGREGATOR_CLASS (parent_class)->negotiated_caps) - if (!GST_VIDEO_AGGREGATOR_CLASS (parent_class)->negotiated_caps (vagg, - caps)) + if (GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps) + if (!GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps)) return FALSE; /* Update the glview_convert output */ diff --git a/ext/gl/gstglvideomixer.c b/ext/gl/gstglvideomixer.c index 06bdf3e102..10251e6792 100644 --- a/ext/gl/gstglvideomixer.c +++ b/ext/gl/gstglvideomixer.c @@ -453,9 +453,8 @@ static void gst_gl_video_mixer_set_property (GObject * object, guint prop_id, static void gst_gl_video_mixer_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps, - GstCaps * filter); -static GstCaps *_fixate_caps (GstVideoAggregator * vagg, GstCaps * caps); +static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps); +static GstCaps *_fixate_caps (GstAggregator * agg, GstCaps * caps); static gboolean gst_gl_video_mixer_propose_allocation (GstGLBaseMixer * base_mix, GstGLBaseMixerPad * base_pad, GstQuery * decide_query, GstQuery * query); @@ -874,9 +873,9 @@ gst_gl_video_mixer_class_init (GstGLVideoMixerClass * klass) gst_gl_video_mixer_process_textures; vagg_class->update_caps = _update_caps; - vagg_class->fixate_caps = _fixate_caps; agg_class->sinkpads_type = GST_TYPE_GL_VIDEO_MIXER_PAD; + agg_class->fixate_src_caps = _fixate_caps; mix_class->propose_allocation = gst_gl_video_mixer_propose_allocation; @@ -986,7 +985,7 @@ _mixer_pad_get_output_size (GstGLVideoMixer * mix, } static GstCaps * -_update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) +_update_caps (GstVideoAggregator * vagg, GstCaps * caps) { GstCaps *ret; GList *l; @@ -1014,18 +1013,15 @@ _update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) GST_OBJECT_UNLOCK (vagg); - if (filter) { - ret = gst_caps_intersect (caps, filter); - } else { - ret = gst_caps_ref (caps); - } + ret = gst_caps_ref (caps); return ret; } static GstCaps * -_fixate_caps (GstVideoAggregator * vagg, GstCaps * caps) +_fixate_caps (GstAggregator * agg, GstCaps * caps) { + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); GstGLVideoMixer *mix = GST_GL_VIDEO_MIXER (vagg); gint best_width = 0, best_height = 0; gint best_fps_n = 0, best_fps_d = 0; diff --git a/gst-libs/gst/audio/gstaudioaggregator.c b/gst-libs/gst/audio/gstaudioaggregator.c index 2eb8a844ed..f5c6c2be15 100644 --- a/gst-libs/gst/audio/gstaudioaggregator.c +++ b/gst-libs/gst/audio/gstaudioaggregator.c @@ -144,8 +144,6 @@ struct _GstAudioAggregatorPrivate { GMutex mutex; - gboolean send_caps; /* aagg lock */ - /* All three properties are unprotected, can't be modified while streaming */ /* Size in frames that is output per buffer */ GstClockTime output_buffer_duration; @@ -189,6 +187,8 @@ static GstFlowReturn gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout); static gboolean sync_pad_values (GstAudioAggregator * aagg, GstAudioAggregatorPad * pad); +static gboolean gst_audio_aggregator_negotiated_src_caps (GstAggregator * agg, + GstCaps * caps); #define DEFAULT_OUTPUT_BUFFER_DURATION (10 * GST_MSECOND) #define DEFAULT_ALIGNMENT_THRESHOLD (40 * GST_MSECOND) @@ -251,6 +251,8 @@ gst_audio_aggregator_class_init (GstAudioAggregatorClass * klass) GST_DEBUG_FUNCPTR (gst_audio_aggregator_aggregate); gstaggregator_class->clip = GST_DEBUG_FUNCPTR (gst_audio_aggregator_do_clip); gstaggregator_class->get_next_time = gst_audio_aggregator_get_next_time; + gstaggregator_class->negotiated_src_caps = + gst_audio_aggregator_negotiated_src_caps; klass->create_output_buffer = gst_audio_aggregator_create_output_buffer; @@ -656,9 +658,10 @@ gst_audio_aggregator_set_sink_caps (GstAudioAggregator * aagg, } -gboolean -gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps) +static gboolean +gst_audio_aggregator_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) { + GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (agg); GstAudioInfo info; if (!gst_audio_info_from_caps (&info, caps)) { @@ -674,8 +677,6 @@ gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps) gst_caps_replace (&aagg->current_caps, caps); memcpy (&aagg->info, &info, sizeof (info)); - aagg->priv->send_caps = TRUE; - } GST_OBJECT_UNLOCK (aagg); @@ -683,7 +684,9 @@ gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps) /* send caps event later, after stream-start event */ - return TRUE; + return + GST_AGGREGATOR_CLASS + (gst_audio_aggregator_parent_class)->negotiated_src_caps (agg, caps); } @@ -1132,21 +1135,13 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) GST_OBJECT_UNLOCK (agg); GST_AUDIO_AGGREGATOR_UNLOCK (aagg); - return GST_FLOW_OK; + return GST_AGGREGATOR_FLOW_NEED_DATA; } else { GST_OBJECT_UNLOCK (agg); goto not_negotiated; } } - if (aagg->priv->send_caps) { - GST_OBJECT_UNLOCK (agg); - gst_aggregator_set_src_caps (agg, aagg->current_caps); - GST_OBJECT_LOCK (agg); - - aagg->priv->send_caps = FALSE; - } - rate = GST_AUDIO_INFO_RATE (&aagg->info); bpf = GST_AUDIO_INFO_BPF (&aagg->info); @@ -1296,7 +1291,7 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) /* We dropped a buffer, retry */ GST_LOG_OBJECT (aagg, "A pad dropped a buffer, wait for the next one"); GST_AUDIO_AGGREGATOR_UNLOCK (aagg); - return GST_FLOW_OK; + return GST_AGGREGATOR_FLOW_NEED_DATA; } if (!is_done && !is_eos) { @@ -1304,7 +1299,7 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) GST_LOG_OBJECT (aagg, "We're not done yet for the current offset, waiting for more data"); GST_AUDIO_AGGREGATOR_UNLOCK (aagg); - return GST_FLOW_OK; + return GST_AGGREGATOR_FLOW_NEED_DATA; } if (is_eos) { diff --git a/gst-libs/gst/audio/gstaudioaggregator.h b/gst-libs/gst/audio/gstaudioaggregator.h index 304bad2871..be76349a43 100644 --- a/gst-libs/gst/audio/gstaudioaggregator.h +++ b/gst-libs/gst/audio/gstaudioaggregator.h @@ -162,9 +162,6 @@ void gst_audio_aggregator_set_sink_caps (GstAudioAggregator * aagg, GstAudioAggregatorPad * pad, GstCaps * caps); -gboolean -gst_audio_aggregator_set_src_caps (GstAudioAggregator * aagg, GstCaps * caps); - G_END_DECLS diff --git a/gst-libs/gst/base/gstaggregator.c b/gst-libs/gst/base/gstaggregator.c index 46b3c5d9f1..3d64903ae4 100644 --- a/gst-libs/gst/base/gstaggregator.c +++ b/gst-libs/gst/base/gstaggregator.c @@ -809,6 +809,116 @@ gst_aggregator_pad_set_flushing (GstAggregatorPad * aggpad, PAD_UNLOCK (aggpad); } +static GstFlowReturn +gst_aggregator_default_update_src_caps (GstAggregator * agg, GstCaps * caps, + GstCaps ** ret) +{ + *ret = gst_caps_ref (caps); + + return GST_FLOW_OK; +} + +static GstCaps * +gst_aggregator_default_fixate_src_caps (GstAggregator * agg, GstCaps * caps) +{ + caps = gst_caps_fixate (caps); + + return caps; +} + +static gboolean +gst_aggregator_default_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) +{ + return TRUE; +} + +/* WITH SRC_LOCK held */ +static GstFlowReturn +gst_aggregator_update_src_caps (GstAggregator * self) +{ + GstAggregatorClass *agg_klass = GST_AGGREGATOR_GET_CLASS (self); + GstCaps *downstream_caps, *template_caps, *caps = NULL; + GstFlowReturn ret = GST_FLOW_OK; + + template_caps = gst_pad_get_pad_template_caps (self->srcpad); + downstream_caps = gst_pad_peer_query_caps (self->srcpad, template_caps); + + if (gst_caps_is_empty (downstream_caps)) { + GST_INFO_OBJECT (self, "Downstream caps (%" + GST_PTR_FORMAT ") not compatible with pad template caps (%" + GST_PTR_FORMAT ")", downstream_caps, template_caps); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + + g_assert (agg_klass->update_src_caps); + GST_DEBUG_OBJECT (self, "updating caps from %" GST_PTR_FORMAT, + downstream_caps); + ret = agg_klass->update_src_caps (self, downstream_caps, &caps); + if (ret < GST_FLOW_OK) { + GST_WARNING_OBJECT (self, "Subclass failed to update provided caps"); + goto done; + } + if ((caps == NULL || gst_caps_is_empty (caps)) && ret >= GST_FLOW_OK) { + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps); + +#ifdef GST_ENABLE_EXTRA_CHECKS + if (!gst_caps_is_subset (caps, template_caps)) { + GstCaps *intersection; + + GST_ERROR_OBJECT (self, + "update_src_caps returned caps %" GST_PTR_FORMAT + " which are not a real subset of the template caps %" + GST_PTR_FORMAT, caps, template_caps); + g_warning ("%s: update_src_caps returned caps which are not a real " + "subset of the filter caps", GST_ELEMENT_NAME (self)); + + intersection = + gst_caps_intersect_full (template_caps, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + caps = intersection; + } +#endif + + if (gst_caps_is_any (caps)) { + goto done; + } + + if (!gst_caps_is_fixed (caps)) { + g_assert (agg_klass->fixate_src_caps); + + GST_DEBUG_OBJECT (self, "fixate caps from %" GST_PTR_FORMAT, caps); + if (!(caps = agg_klass->fixate_src_caps (self, caps))) { + GST_WARNING_OBJECT (self, "Subclass failed to fixate provided caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + GST_DEBUG_OBJECT (self, " to %" GST_PTR_FORMAT, caps); + } + + if (agg_klass->negotiated_src_caps) { + if (!agg_klass->negotiated_src_caps (self, caps)) { + GST_WARNING_OBJECT (self, "Subclass failed to accept negotiated caps"); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + } + + gst_aggregator_set_src_caps (self, caps); + +done: + gst_caps_unref (downstream_caps); + gst_caps_unref (template_caps); + + if (caps) + gst_caps_unref (caps); + + return ret; +} + static void gst_aggregator_aggregate_func (GstAggregator * self) { @@ -823,7 +933,7 @@ gst_aggregator_aggregate_func (GstAggregator * self) GST_LOG_OBJECT (self, "Checking aggregate"); while (priv->send_eos && priv->running) { - GstFlowReturn flow_return; + GstFlowReturn flow_return = GST_FLOW_OK; gboolean processed_event = FALSE; gst_aggregator_iterate_sinkpads (self, check_events, NULL); @@ -835,8 +945,19 @@ gst_aggregator_aggregate_func (GstAggregator * self) if (processed_event) continue; - GST_TRACE_OBJECT (self, "Actually aggregating!"); - flow_return = klass->aggregate (self, timeout); + if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (self))) { + flow_return = gst_aggregator_update_src_caps (self); + if (flow_return != GST_FLOW_OK) + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); + } + + if (timeout || flow_return >= GST_FLOW_OK) { + GST_TRACE_OBJECT (self, "Actually aggregating!"); + flow_return = klass->aggregate (self, timeout); + } + + if (flow_return == GST_AGGREGATOR_FLOW_NEED_DATA) + continue; GST_OBJECT_LOCK (self); if (flow_return == GST_FLOW_FLUSHING && priv->flush_seeking) { @@ -1979,6 +2100,9 @@ gst_aggregator_class_init (GstAggregatorClass * klass) klass->src_query = gst_aggregator_default_src_query; klass->create_new_pad = gst_aggregator_default_create_new_pad; + klass->update_src_caps = gst_aggregator_default_update_src_caps; + klass->fixate_src_caps = gst_aggregator_default_fixate_src_caps; + klass->negotiated_src_caps = gst_aggregator_default_negotiated_src_caps; gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_aggregator_request_new_pad); diff --git a/gst-libs/gst/base/gstaggregator.h b/gst-libs/gst/base/gstaggregator.h index 38d260570e..be989ad261 100644 --- a/gst-libs/gst/base/gstaggregator.h +++ b/gst-libs/gst/base/gstaggregator.h @@ -120,6 +120,7 @@ gboolean gst_aggregator_pad_is_eos (GstAggregatorPad * pad); #define GST_IS_AGGREGATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AGGREGATOR)) #define GST_FLOW_NOT_HANDLED GST_FLOW_CUSTOM_SUCCESS +#define GST_AGGREGATOR_FLOW_NEED_DATA GST_FLOW_CUSTOM_ERROR /** * GstAggregator: @@ -195,6 +196,18 @@ struct _GstAggregator * based aggregation to occur. Defaults to returning * GST_CLOCK_TIME_NONE causing the element to wait for buffers * on all sink pads before aggregating. + * @update_src_caps: Lets subclasses update the #GstCaps representing + * the src pad caps before usage. The result should end up + * in @ret. Return %GST_AGGREGATOR_FLOW_NEED_DATA to indicate that the + * element needs more information (caps, a buffer, etc) to + * choose the correct caps. Should return ANY caps if the + * stream has not caps at all. + * @fixate_src_caps: Optional. + * Fixate and return the src pad caps provided. The function takes + * ownership of @caps and returns a fixated version of + * @caps. @caps is not guaranteed to be writable. + * @negotiated_src_caps: Optional. + * Notifies subclasses what caps format has been negotiated * * The aggregator base class will handle in a thread-safe way all manners of * concurrent flushes, seeks, pad additions and removals, leaving to the @@ -250,6 +263,13 @@ struct _GstAggregatorClass { GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps); + GstFlowReturn (*update_src_caps) (GstAggregator * self, + GstCaps * caps, + GstCaps ** ret); + GstCaps * (*fixate_src_caps) (GstAggregator * self, + GstCaps * caps); + gboolean (*negotiated_src_caps) (GstAggregator * self, + GstCaps * caps); /*< private >*/ gpointer _gst_reserved[GST_PADDING_LARGE]; diff --git a/gst-libs/gst/video/gstvideoaggregator.c b/gst-libs/gst/video/gstvideoaggregator.c index 8310fd2175..7cdce00fa6 100644 --- a/gst-libs/gst/video/gstvideoaggregator.c +++ b/gst-libs/gst/video/gstvideoaggregator.c @@ -535,60 +535,11 @@ gst_video_aggregator_find_best_format (GstVideoAggregator * vagg, g_hash_table_unref (formats_table); } -/* WITH GST_VIDEO_AGGREGATOR_LOCK TAKEN */ -static gboolean -gst_video_aggregator_src_setcaps (GstVideoAggregator * vagg, GstCaps * caps) -{ - GstAggregator *agg = GST_AGGREGATOR (vagg); - gboolean ret = FALSE; - GstVideoInfo info; - - GstPad *pad = GST_AGGREGATOR (vagg)->srcpad; - - GST_INFO_OBJECT (pad, "set src caps: %" GST_PTR_FORMAT, caps); - - if (!gst_video_info_from_caps (&info, caps)) - goto done; - - ret = TRUE; - - if (GST_VIDEO_INFO_FPS_N (&vagg->info) != GST_VIDEO_INFO_FPS_N (&info) || - GST_VIDEO_INFO_FPS_D (&vagg->info) != GST_VIDEO_INFO_FPS_D (&info)) { - if (agg->segment.position != -1) { - vagg->priv->nframes = 0; - /* The timestamp offset will be updated based on the - * segment position the next time we aggregate */ - GST_DEBUG_OBJECT (vagg, - "Resetting frame counter because of framerate change"); - } - gst_video_aggregator_reset_qos (vagg); - } - - vagg->info = info; - - if (vagg->priv->current_caps == NULL || - gst_caps_is_equal (caps, vagg->priv->current_caps) == FALSE) { - GstClockTime latency; - - gst_caps_replace (&vagg->priv->current_caps, caps); - GST_VIDEO_AGGREGATOR_UNLOCK (vagg); - - gst_aggregator_set_src_caps (agg, caps); - latency = gst_util_uint64_scale (GST_SECOND, - GST_VIDEO_INFO_FPS_D (&info), GST_VIDEO_INFO_FPS_N (&info)); - gst_aggregator_set_latency (agg, latency, latency); - - GST_VIDEO_AGGREGATOR_LOCK (vagg); - } - -done: - return ret; -} - static GstCaps * -gst_video_aggregator_default_fixate_caps (GstVideoAggregator * vagg, +gst_video_aggregator_default_fixate_src_caps (GstAggregator * agg, GstCaps * caps) { + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); gint best_width = -1, best_height = -1; gint best_fps_n = -1, best_fps_d = -1; gdouble best_fps = -1.; @@ -634,6 +585,7 @@ gst_video_aggregator_default_fixate_caps (GstVideoAggregator * vagg, best_fps = 25.0; } + caps = gst_caps_make_writable (caps); s = gst_caps_get_structure (caps, 0); gst_structure_fixate_field_nearest_int (s, "width", best_width); gst_structure_fixate_field_nearest_int (s, "height", best_height); @@ -648,7 +600,7 @@ gst_video_aggregator_default_fixate_caps (GstVideoAggregator * vagg, static GstCaps * gst_video_aggregator_default_update_caps (GstVideoAggregator * vagg, - GstCaps * caps, GstCaps * filter) + GstCaps * caps) { GstVideoAggregatorClass *vagg_klass = GST_VIDEO_AGGREGATOR_GET_CLASS (vagg); GstCaps *ret, *best_format_caps; @@ -682,38 +634,59 @@ gst_video_aggregator_default_update_caps (GstVideoAggregator * vagg, gst_video_chroma_to_string (best_info.chroma_site), NULL); ret = gst_caps_merge (best_format_caps, gst_caps_ref (caps)); - if (filter) { - GstCaps *tmp; - tmp = gst_caps_intersect (ret, filter); - gst_caps_unref (ret); - ret = tmp; - } - return ret; } -/* WITH GST_VIDEO_AGGREGATOR_LOCK TAKEN */ -static gboolean -gst_video_aggregator_update_src_caps (GstVideoAggregator * vagg) +static GstFlowReturn +gst_video_aggregator_default_update_src_caps (GstAggregator * agg, + GstCaps * caps, GstCaps ** ret) { - GstVideoAggregatorClass *vagg_klass = GST_VIDEO_AGGREGATOR_GET_CLASS (vagg); - GstVideoAggregatorPadClass *vaggpad_klass = g_type_class_peek - (GST_AGGREGATOR_GET_CLASS (vagg)->sinkpads_type); - GstAggregator *agg = GST_AGGREGATOR (vagg); - gboolean ret = TRUE, at_least_one_pad_configured = FALSE; - gboolean at_least_one_alpha = FALSE; - GstCaps *downstream_caps; + GstVideoAggregatorClass *vagg_klass = GST_VIDEO_AGGREGATOR_GET_CLASS (agg); + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); + gboolean at_least_one_pad_configured = FALSE; GList *l; - downstream_caps = gst_pad_get_allowed_caps (agg->srcpad); + GST_OBJECT_LOCK (vagg); + for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { + GstVideoAggregatorPad *mpad = l->data; - if (!downstream_caps || gst_caps_is_empty (downstream_caps)) { - GST_INFO_OBJECT (vagg, "No downstream caps found %" - GST_PTR_FORMAT, downstream_caps); - if (downstream_caps) - gst_caps_unref (downstream_caps); - return FALSE; + if (GST_VIDEO_INFO_WIDTH (&mpad->info) == 0 + || GST_VIDEO_INFO_HEIGHT (&mpad->info) == 0) + continue; + + at_least_one_pad_configured = TRUE; } + GST_OBJECT_UNLOCK (vagg); + + if (!at_least_one_pad_configured) { + /* We couldn't decide the output video info because the sinkpads don't have + * all the caps yet, so we mark the pad as needing a reconfigure. This + * allows aggregate() to skip ahead a bit and try again later. */ + GST_DEBUG_OBJECT (vagg, "Couldn't decide output video info"); + gst_pad_mark_reconfigure (agg->srcpad); + return GST_AGGREGATOR_FLOW_NEED_DATA; + } + + g_assert (vagg_klass->update_caps); + + *ret = vagg_klass->update_caps (vagg, caps); + + return GST_FLOW_OK; +} + +static gboolean +gst_video_aggregator_default_negotiated_src_caps (GstAggregator * agg, + GstCaps * caps) +{ + GstVideoAggregatorPadClass *vaggpad_klass = g_type_class_peek + (GST_AGGREGATOR_GET_CLASS (agg)->sinkpads_type); + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); + gboolean at_least_one_alpha = FALSE; + const GstVideoFormatInfo *finfo; + GstVideoInfo info; + GList *l; + + GST_INFO_OBJECT (agg->srcpad, "set src caps: %" GST_PTR_FORMAT, caps); GST_OBJECT_LOCK (vagg); for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { @@ -725,101 +698,59 @@ gst_video_aggregator_update_src_caps (GstVideoAggregator * vagg) if (mpad->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_ALPHA) at_least_one_alpha = TRUE; - - at_least_one_pad_configured = TRUE; } GST_OBJECT_UNLOCK (vagg); - if (at_least_one_pad_configured) { - GstCaps *caps, *peercaps; + if (!gst_video_info_from_caps (&info, caps)) + return FALSE; - peercaps = gst_pad_peer_query_caps (agg->srcpad, NULL); - - g_assert (vagg_klass->update_caps); - GST_DEBUG_OBJECT (vagg, "updating caps from %" GST_PTR_FORMAT, - downstream_caps); - GST_DEBUG_OBJECT (vagg, " with filter %" GST_PTR_FORMAT, peercaps); - if (!(caps = vagg_klass->update_caps (vagg, downstream_caps, peercaps)) || - gst_caps_is_empty (caps)) { - GST_WARNING_OBJECT (vagg, "Subclass failed to update provided caps"); - gst_caps_unref (downstream_caps); - if (peercaps) - gst_caps_unref (peercaps); - ret = FALSE; - goto done; + if (GST_VIDEO_INFO_FPS_N (&vagg->info) != GST_VIDEO_INFO_FPS_N (&info) || + GST_VIDEO_INFO_FPS_D (&vagg->info) != GST_VIDEO_INFO_FPS_D (&info)) { + if (agg->segment.position != -1) { + vagg->priv->nframes = 0; + /* The timestamp offset will be updated based on the + * segment position the next time we aggregate */ + GST_DEBUG_OBJECT (vagg, + "Resetting frame counter because of framerate change"); } - GST_DEBUG_OBJECT (vagg, " to %" GST_PTR_FORMAT, caps); - - gst_caps_unref (downstream_caps); - if (peercaps) - gst_caps_unref (peercaps); - - if (!gst_caps_is_fixed (caps)) { - g_assert (vagg_klass->fixate_caps); - - caps = gst_caps_make_writable (caps); - GST_DEBUG_OBJECT (vagg, "fixate caps from %" GST_PTR_FORMAT, caps); - if (!(caps = vagg_klass->fixate_caps (vagg, caps))) { - GST_WARNING_OBJECT (vagg, "Subclass failed to fixate provided caps"); - ret = FALSE; - goto done; - } - GST_DEBUG_OBJECT (vagg, " to %" GST_PTR_FORMAT, caps); - } - - { - const GstVideoFormatInfo *finfo; - const gchar *v_format_str; - GstVideoFormat v_format; - GstStructure *s; - - s = gst_caps_get_structure (caps, 0); - v_format_str = gst_structure_get_string (s, "format"); - g_return_val_if_fail (v_format_str != NULL, FALSE); - v_format = gst_video_format_from_string (v_format_str); - g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE); - finfo = gst_video_format_get_info (v_format); - g_return_val_if_fail (finfo != NULL, FALSE); - - if (at_least_one_alpha && !(finfo->flags & GST_VIDEO_FORMAT_FLAG_ALPHA)) { - GST_ELEMENT_ERROR (vagg, CORE, NEGOTIATION, - ("At least one of the input pads contains alpha, but configured caps don't support alpha."), - ("Either convert your inputs to not contain alpha or add a videoconvert after the aggregator")); - ret = FALSE; - goto done; - } - } - - gst_video_info_from_caps (&vagg->info, caps); - - if (vaggpad_klass->set_info) { - /* Then browse the sinks once more, setting or unsetting conversion if needed */ - for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { - GstVideoAggregatorPad *pad = GST_VIDEO_AGGREGATOR_PAD (l->data); - - if (!vaggpad_klass->set_info (pad, vagg, &pad->info, &vagg->info)) { - return FALSE; - } - } - } - - if (gst_video_aggregator_src_setcaps (vagg, caps)) { - if (vagg_klass->negotiated_caps) - ret = - GST_VIDEO_AGGREGATOR_GET_CLASS (vagg)->negotiated_caps (vagg, caps); - } - gst_caps_unref (caps); - } else { - /* We couldn't decide the output video info because the sinkpads don't have - * all the caps yet, so we mark the pad as needing a reconfigure. This - * allows aggregate() to skip ahead a bit and try again later. */ - GST_DEBUG_OBJECT (vagg, "Couldn't decide output video info"); - gst_pad_mark_reconfigure (agg->srcpad); - ret = FALSE; + gst_video_aggregator_reset_qos (vagg); } -done: - return ret; + vagg->info = info; + + finfo = vagg->info.finfo; + + if (at_least_one_alpha && !(finfo->flags & GST_VIDEO_FORMAT_FLAG_ALPHA)) { + GST_ELEMENT_ERROR (vagg, CORE, NEGOTIATION, + ("At least one of the input pads contains alpha, but configured caps don't support alpha."), + ("Either convert your inputs to not contain alpha or add a videoconvert after the aggregator")); + return FALSE; + } + + if (vaggpad_klass->set_info) { + /* Then browse the sinks once more, setting or unsetting conversion if needed */ + for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { + GstVideoAggregatorPad *pad = GST_VIDEO_AGGREGATOR_PAD (l->data); + + if (!vaggpad_klass->set_info (pad, vagg, &pad->info, &vagg->info)) { + return FALSE; + } + } + } + + if (vagg->priv->current_caps == NULL || + gst_caps_is_equal (caps, vagg->priv->current_caps) == FALSE) { + GstClockTime latency; + + gst_caps_replace (&vagg->priv->current_caps, caps); + + gst_aggregator_set_src_caps (agg, caps); + latency = gst_util_uint64_scale (GST_SECOND, + GST_VIDEO_INFO_FPS_D (&vagg->info), GST_VIDEO_INFO_FPS_N (&vagg->info)); + gst_aggregator_set_latency (agg, latency, latency); + } + + return TRUE; } static gboolean @@ -1101,7 +1032,6 @@ gst_video_aggregator_reset (GstVideoAggregator * vagg) GST_OBJECT_UNLOCK (vagg); } -#define GST_FLOW_NEEDS_DATA GST_FLOW_CUSTOM_ERROR static gint gst_video_aggregator_fill_queues (GstVideoAggregator * vagg, GstClockTime output_start_running_time, @@ -1309,7 +1239,7 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg, gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg)); if (need_more_data) - return GST_FLOW_NEEDS_DATA; + return GST_AGGREGATOR_FLOW_NEED_DATA; if (eos) return GST_FLOW_EOS; @@ -1471,66 +1401,36 @@ gst_video_aggregator_get_next_time (GstAggregator * agg) return next_time; } -static GstFlowReturn -gst_video_aggregator_check_reconfigure (GstVideoAggregator * vagg, - gboolean timeout) +static void +gst_video_aggregator_advance_on_timeout (GstVideoAggregator * vagg) { - GstAggregator *agg = (GstAggregator *) vagg; + GstAggregator *agg = GST_AGGREGATOR (vagg); + guint64 frame_duration; + gint fps_d, fps_n; - if (GST_VIDEO_INFO_FORMAT (&vagg->info) == GST_VIDEO_FORMAT_UNKNOWN - || gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg))) { - gboolean ret; - - restart: - ret = gst_video_aggregator_update_src_caps (vagg); - if (!ret) { - gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg)); - if (timeout) { - guint64 frame_duration; - gint fps_d, fps_n; - - GST_DEBUG_OBJECT (vagg, - "Got timeout before receiving any caps, don't output anything"); - - if (agg->segment.position == -1) { - if (agg->segment.rate > 0.0) - agg->segment.position = agg->segment.start; - else - agg->segment.position = agg->segment.stop; - } - - /* Advance position */ - fps_d = GST_VIDEO_INFO_FPS_D (&vagg->info) ? - GST_VIDEO_INFO_FPS_D (&vagg->info) : 1; - fps_n = GST_VIDEO_INFO_FPS_N (&vagg->info) ? - GST_VIDEO_INFO_FPS_N (&vagg->info) : 25; - /* Default to 25/1 if no "best fps" is known */ - frame_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); - if (agg->segment.rate > 0.0) - agg->segment.position += frame_duration; - else if (agg->segment.position > frame_duration) - agg->segment.position -= frame_duration; - else - agg->segment.position = 0; - vagg->priv->nframes++; - return GST_FLOW_NEEDS_DATA; - } else { - if (GST_PAD_IS_FLUSHING (GST_AGGREGATOR_SRC_PAD (vagg))) - return GST_FLOW_FLUSHING; - else - return GST_FLOW_NOT_NEGOTIATED; - } - } else { - /* It is possible that during gst_video_aggregator_update_src_caps() - * we got a caps change on one of the sink pads, in which case we need - * to redo the negotiation - * - https://bugzilla.gnome.org/show_bug.cgi?id=755782 */ - if (gst_pad_check_reconfigure (GST_AGGREGATOR_SRC_PAD (vagg))) - goto restart; - } + GST_OBJECT_LOCK (agg); + if (agg->segment.position == -1) { + if (agg->segment.rate > 0.0) + agg->segment.position = agg->segment.start; + else + agg->segment.position = agg->segment.stop; } - return GST_FLOW_OK; + /* Advance position */ + fps_d = GST_VIDEO_INFO_FPS_D (&vagg->info) ? + GST_VIDEO_INFO_FPS_D (&vagg->info) : 1; + fps_n = GST_VIDEO_INFO_FPS_N (&vagg->info) ? + GST_VIDEO_INFO_FPS_N (&vagg->info) : 25; + /* Default to 25/1 if no "best fps" is known */ + frame_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n); + if (agg->segment.rate > 0.0) + agg->segment.position += frame_duration; + else if (agg->segment.position > frame_duration) + agg->segment.position -= frame_duration; + else + agg->segment.position = 0; + vagg->priv->nframes++; + GST_OBJECT_UNLOCK (agg); } static GstFlowReturn @@ -1546,10 +1446,10 @@ gst_video_aggregator_aggregate (GstAggregator * agg, gboolean timeout) GST_VIDEO_AGGREGATOR_LOCK (vagg); restart: - flow_ret = gst_video_aggregator_check_reconfigure (vagg, timeout); - if (flow_ret != GST_FLOW_OK) { - if (flow_ret == GST_FLOW_NEEDS_DATA) - flow_ret = GST_FLOW_OK; + if (GST_VIDEO_INFO_FORMAT (&vagg->info) == GST_VIDEO_FORMAT_UNKNOWN) { + if (timeout) + gst_video_aggregator_advance_on_timeout (vagg); + flow_ret = GST_AGGREGATOR_FLOW_NEED_DATA; goto unlock_and_return; } @@ -1591,9 +1491,8 @@ restart: output_end_running_time); } - if (flow_ret == GST_FLOW_NEEDS_DATA && !timeout) { + if (flow_ret == GST_AGGREGATOR_FLOW_NEED_DATA && !timeout) { GST_DEBUG_OBJECT (vagg, "Need more data for decisions"); - flow_ret = GST_FLOW_OK; goto unlock_and_return; } else if (flow_ret == GST_FLOW_EOS) { GST_DEBUG_OBJECT (vagg, "All sinkpads are EOS -- forwarding"); @@ -2187,11 +2086,14 @@ gst_video_aggregator_class_init (GstVideoAggregatorClass * klass) agg_class->src_event = gst_video_aggregator_src_event; agg_class->src_query = gst_video_aggregator_src_query; agg_class->get_next_time = gst_video_aggregator_get_next_time; + agg_class->update_src_caps = gst_video_aggregator_default_update_src_caps; + agg_class->fixate_src_caps = gst_video_aggregator_default_fixate_src_caps; + agg_class->negotiated_src_caps = + gst_video_aggregator_default_negotiated_src_caps; klass->find_best_format = gst_video_aggregator_find_best_format; klass->get_output_buffer = gst_video_aggregator_get_output_buffer; klass->update_caps = gst_video_aggregator_default_update_caps; - klass->fixate_caps = gst_video_aggregator_default_fixate_caps; /* Register the pad class */ g_type_class_ref (GST_TYPE_VIDEO_AGGREGATOR_PAD); diff --git a/gst-libs/gst/video/gstvideoaggregator.h b/gst-libs/gst/video/gstvideoaggregator.h index 6204bdd037..ced6124aec 100644 --- a/gst-libs/gst/video/gstvideoaggregator.h +++ b/gst-libs/gst/video/gstvideoaggregator.h @@ -73,9 +73,6 @@ struct _GstVideoAggregator * @update_caps: Optional. * Lets subclasses update the #GstCaps representing * the src pad caps before usage. Return %NULL to indicate failure. - * @fixate_caps: Fixate and return the src pad caps provided. The function takes - * ownership of @caps and returns a fixated version of - * @caps. @caps is not guaranteed to be writable. * @aggregate_frames: Lets subclasses aggregate frames that are ready. Subclasses * should iterate the GstElement.sinkpads and use the already * mapped #GstVideoFrame from GstVideoAggregatorPad.aggregated_frame @@ -97,16 +94,11 @@ struct _GstVideoAggregatorClass /*< public >*/ GstCaps * (*update_caps) (GstVideoAggregator * videoaggregator, - GstCaps * caps, - GstCaps * filter_caps); - GstCaps * (*fixate_caps) (GstVideoAggregator * videoaggregator, GstCaps * caps); GstFlowReturn (*aggregate_frames) (GstVideoAggregator * videoaggregator, GstBuffer * outbuffer); GstFlowReturn (*get_output_buffer) (GstVideoAggregator * videoaggregator, GstBuffer ** outbuffer); - gboolean (*negotiated_caps) (GstVideoAggregator * videoaggregator, - GstCaps * caps); void (*find_best_format) (GstVideoAggregator * vagg, GstCaps * downstream_caps, GstVideoInfo * best_info, diff --git a/gst/audiomixer/gstaudiointerleave.c b/gst/audiomixer/gstaudiointerleave.c index 8d99b3ce13..dfae4a51ae 100644 --- a/gst/audiomixer/gstaudiointerleave.c +++ b/gst/audiomixer/gstaudiointerleave.c @@ -432,10 +432,10 @@ gst_audio_interleave_setcaps (GstAudioInterleave * self, GstPad * pad, GST_DEBUG_OBJECT (self, "setting sinkcaps %" GST_PTR_FORMAT, sinkcaps); gst_caps_replace (&self->sinkcaps, sinkcaps); + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (aagg)); gst_caps_unref (sinkcaps); new = TRUE; - self->new_caps = TRUE; } if (self->channel_positions_from_input @@ -504,52 +504,40 @@ gst_audio_interleave_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad, } static GstFlowReturn -gst_audio_interleave_aggregate (GstAggregator * aggregator, gboolean timeout) +gst_audio_interleave_update_src_caps (GstAggregator * agg, GstCaps * caps, + GstCaps ** ret) { - GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (aggregator); - GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (aggregator); + GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); + GstStructure *s; - GST_OBJECT_LOCK (aggregator); - if (self->new_caps) { - GstCaps *srccaps; - GstStructure *s; - gboolean ret; + /* This means that either no caps have been set on the sink pad (if + * sinkcaps is NULL) or that there is no sink pad (if channels == 0). + */ + if (self->sinkcaps == NULL || self->channels == 0) + return GST_FLOW_NOT_NEGOTIATED; - if (self->sinkcaps == NULL || self->channels == 0) { - /* In this case, let the base class handle it */ - goto not_negotiated; - } + *ret = gst_caps_copy (self->sinkcaps); + s = gst_caps_get_structure (*ret, 0); - srccaps = gst_caps_copy (self->sinkcaps); - s = gst_caps_get_structure (srccaps, 0); + gst_structure_set (s, "channels", G_TYPE_INT, self->channels, "layout", + G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK, + gst_audio_interleave_get_channel_mask (self), NULL); - gst_structure_set (s, "channels", G_TYPE_INT, self->channels, "layout", - G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK, - gst_audio_interleave_get_channel_mask (self), NULL); + return GST_FLOW_OK; +} +static gboolean +gst_audio_interleave_negotiated_src_caps (GstAggregator * agg, GstCaps * caps) +{ + GstAudioInterleave *self = GST_AUDIO_INTERLEAVE (agg); + GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (self); - GST_OBJECT_UNLOCK (aggregator); - ret = gst_audio_aggregator_set_src_caps (aagg, srccaps); - gst_caps_unref (srccaps); + if (!GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps)) + return FALSE; - if (!ret) - goto src_did_not_accept; + gst_audio_interleave_set_process_function (self, &aagg->info); - GST_OBJECT_LOCK (aggregator); - - gst_audio_interleave_set_process_function (self, &aagg->info); - - self->new_caps = FALSE; - } - -not_negotiated: - GST_OBJECT_UNLOCK (aggregator); - - return GST_AGGREGATOR_CLASS (parent_class)->aggregate (aggregator, timeout); - -src_did_not_accept: - GST_WARNING_OBJECT (self, "src did not accept setcaps()"); - return GST_FLOW_NOT_NEGOTIATED;; + return TRUE; } static void @@ -586,7 +574,8 @@ gst_audio_interleave_class_init (GstAudioInterleaveClass * klass) agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_query); agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audio_interleave_sink_event); agg_class->stop = gst_audio_interleave_stop; - agg_class->aggregate = gst_audio_interleave_aggregate; + agg_class->update_src_caps = gst_audio_interleave_update_src_caps; + agg_class->negotiated_src_caps = gst_audio_interleave_negotiated_src_caps; aagg_class->aggregate_one_buffer = gst_audio_interleave_aggregate_one_buffer; @@ -720,7 +709,6 @@ gst_audio_interleave_stop (GstAggregator * agg) if (!GST_AGGREGATOR_CLASS (parent_class)->stop (agg)) return FALSE; - self->new_caps = FALSE; gst_caps_replace (&self->sinkcaps, NULL); return TRUE; @@ -765,9 +753,7 @@ gst_audio_interleave_request_new_pad (GstElement * element, g_value_unset (&val); /* Update the src caps if we already have them */ - GST_OBJECT_LOCK (self); - self->new_caps = TRUE; - GST_OBJECT_UNLOCK (self); + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); return GST_PAD_CAST (newpad); @@ -804,7 +790,7 @@ gst_audio_interleave_release_pad (GstElement * element, GstPad * pad) ipad->channel--; } - self->new_caps = TRUE; + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (self)); GST_OBJECT_UNLOCK (self); diff --git a/gst/audiomixer/gstaudiointerleave.h b/gst/audiomixer/gstaudiointerleave.h index 6dd82d383c..ef959ceef2 100644 --- a/gst/audiomixer/gstaudiointerleave.h +++ b/gst/audiomixer/gstaudiointerleave.h @@ -58,7 +58,6 @@ struct _GstAudioInterleave { gint padcounter; guint channels; - gboolean new_caps; GstCaps *sinkcaps; GValueArray *channel_positions; diff --git a/gst/audiomixer/gstaudiomixer.c b/gst/audiomixer/gstaudiomixer.c index ac2f49c04b..2233b82c1e 100644 --- a/gst/audiomixer/gstaudiomixer.c +++ b/gst/audiomixer/gstaudiomixer.c @@ -348,7 +348,6 @@ gst_audiomixer_setcaps (GstAudioMixer * audiomixer, GstPad * pad, GstAudioInfo info; GstStructure *s; gint channels = 0; - gboolean ret; caps = gst_caps_copy (orig_caps); @@ -405,20 +404,21 @@ gst_audiomixer_setcaps (GstAudioMixer * audiomixer, GstPad * pad, gst_caps_unref (caps); return FALSE; } + } else { + gst_caps_replace (&aagg->current_caps, caps); + aagg->info = info; + gst_pad_mark_reconfigure (GST_AGGREGATOR_SRC_PAD (agg)); } GST_OBJECT_UNLOCK (audiomixer); - ret = gst_audio_aggregator_set_src_caps (aagg, caps); - - if (ret) - gst_audio_aggregator_set_sink_caps (aagg, GST_AUDIO_AGGREGATOR_PAD (pad), - orig_caps); + gst_audio_aggregator_set_sink_caps (aagg, GST_AUDIO_AGGREGATOR_PAD (pad), + orig_caps); GST_INFO_OBJECT (pad, "handle caps change to %" GST_PTR_FORMAT, caps); gst_caps_unref (caps); - return ret; + return TRUE; /* ERRORS */ invalid_format: @@ -429,6 +429,20 @@ invalid_format: } } +static GstFlowReturn +gst_audiomixer_update_src_caps (GstAggregator * agg, GstCaps * caps, + GstCaps ** ret) +{ + GstAudioAggregator *aagg = GST_AUDIO_AGGREGATOR (agg); + + if (aagg->current_caps == NULL) + return GST_AGGREGATOR_FLOW_NEED_DATA; + + *ret = gst_caps_ref (aagg->current_caps); + + return GST_FLOW_OK; +} + static gboolean gst_audiomixer_sink_event (GstAggregator * agg, GstAggregatorPad * aggpad, GstEvent * event) @@ -495,6 +509,8 @@ gst_audiomixer_class_init (GstAudioMixerClass * klass) agg_class->sink_query = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_query); agg_class->sink_event = GST_DEBUG_FUNCPTR (gst_audiomixer_sink_event); + agg_class->update_src_caps = + GST_DEBUG_FUNCPTR (gst_audiomixer_update_src_caps); aagg_class->aggregate_one_buffer = gst_audiomixer_aggregate_one_buffer; } diff --git a/gst/compositor/compositor.c b/gst/compositor/compositor.c index de3bf22d65..23dc20cda1 100644 --- a/gst/compositor/compositor.c +++ b/gst/compositor/compositor.c @@ -870,8 +870,9 @@ set_functions (GstCompositor * self, GstVideoInfo * info) } static GstCaps * -_fixate_caps (GstVideoAggregator * vagg, GstCaps * caps) +_fixate_caps (GstAggregator * agg, GstCaps * caps) { + GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (agg); GList *l; gint best_width = -1, best_height = -1; gint best_fps_n = -1, best_fps_d = -1; @@ -945,21 +946,21 @@ _fixate_caps (GstVideoAggregator * vagg, GstCaps * caps) } static gboolean -_negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) +_negotiated_caps (GstAggregator * agg, GstCaps * caps) { GstVideoInfo v_info; - GST_DEBUG_OBJECT (vagg, "Negotiated caps %" GST_PTR_FORMAT, caps); + GST_DEBUG_OBJECT (agg, "Negotiated caps %" GST_PTR_FORMAT, caps); if (!gst_video_info_from_caps (&v_info, caps)) return FALSE; - if (!set_functions (GST_COMPOSITOR (vagg), &v_info)) { - GST_ERROR_OBJECT (vagg, "Failed to setup vfuncs"); + if (!set_functions (GST_COMPOSITOR (agg), &v_info)) { + GST_ERROR_OBJECT (agg, "Failed to setup vfuncs"); return FALSE; } - return TRUE; + return GST_AGGREGATOR_CLASS (parent_class)->negotiated_src_caps (agg, caps); } static GstFlowReturn @@ -1090,8 +1091,8 @@ gst_compositor_class_init (GstCompositorClass * klass) agg_class->sinkpads_type = GST_TYPE_COMPOSITOR_PAD; agg_class->sink_query = _sink_query; - videoaggregator_class->fixate_caps = _fixate_caps; - videoaggregator_class->negotiated_caps = _negotiated_caps; + agg_class->fixate_src_caps = _fixate_caps; + agg_class->negotiated_src_caps = _negotiated_caps; videoaggregator_class->aggregate_frames = gst_compositor_aggregate_frames; g_object_class_install_property (gobject_class, PROP_BACKGROUND, diff --git a/tests/check/elements/audiointerleave.c b/tests/check/elements/audiointerleave.c index cb992f393a..f2e820b526 100644 --- a/tests/check/elements/audiointerleave.c +++ b/tests/check/elements/audiointerleave.c @@ -1043,7 +1043,9 @@ GST_START_TEST (test_audiointerleave_2ch_smallbuf) gst_caps_unref (caps); gst_event_unref (ev); - for (i = 0; i < 24; i++) + /* eat the caps processing */ + gst_harness_crank_single_clock_wait (h); + for (i = 0; i < 23; i++) gst_harness_crank_single_clock_wait (h); fail_unless_equals_uint64 (gst_clock_get_time (GST_ELEMENT_CLOCK (h->element)), 750 * GST_MSECOND);