From 97bef4e8a57951450bb42f831a3d8f853900aa92 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 26 Aug 2016 00:29:34 +1000 Subject: [PATCH] glstereomix: Fix caps negotiation The videoaggregator negotiation sequence changed some time back and broke glstereomix. Instead of doing nego incorrectly in the find_best_format() vfunc, do it directly in the update_caps() method. --- ext/gl/gstglstereomix.c | 201 +++++++++++++++++----------------------- ext/gl/gstglstereomix.h | 3 - 2 files changed, 86 insertions(+), 118 deletions(-) diff --git a/ext/gl/gstglstereomix.c b/ext/gl/gstglstereomix.c index 663c1b744a..1c214d8d66 100644 --- a/ext/gl/gstglstereomix.c +++ b/ext/gl/gstglstereomix.c @@ -106,11 +106,6 @@ static gboolean gst_gl_stereo_mix_start (GstAggregator * agg); static gboolean gst_gl_stereo_mix_src_query (GstAggregator * agg, GstQuery * query); -static void -gst_gl_stereo_mix_find_best_format (GstVideoAggregator * vagg, - GstCaps * downstream_caps, GstVideoInfo * best_info, - gboolean * at_least_one_alpha); - static void gst_gl_stereo_mix_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_gl_stereo_mix_get_property (GObject * object, guint prop_id, @@ -163,7 +158,6 @@ gst_gl_stereo_mix_class_init (GstGLStereoMixClass * klass) videoaggregator_class->negotiated_caps = _negotiated_caps; videoaggregator_class->get_output_buffer = gst_gl_stereo_mix_get_output_buffer; - videoaggregator_class->find_best_format = gst_gl_stereo_mix_find_best_format; base_mix_class->supported_gl_api = GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3; @@ -438,13 +432,97 @@ get_converted_caps (GstGLStereoMix * mix, GstCaps * caps) return result; } -/* Return the possible output caps we decided in find_best_format() */ +/* Return the possible output caps based on inputs and downstream prefs */ static GstCaps * _update_caps (GstVideoAggregator * vagg, GstCaps * caps, GstCaps * filter) { GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg); + GList *l; + gint best_width = -1, best_height = -1; + gdouble best_fps = -1, cur_fps; + gint best_fps_n = 0, best_fps_d = 1; + GstVideoInfo *mix_info; + GstCaps *blend_caps, *tmp_caps; + GstCaps *out_caps; - return gst_caps_ref (mix->out_caps); + GST_OBJECT_LOCK (vagg); + + for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { + GstVideoAggregatorPad *pad = l->data; + GstVideoInfo tmp = pad->info; + gint this_width, this_height; + gint fps_n, fps_d; + + if (!pad->info.finfo) + continue; + + /* This can happen if we release a pad and another pad hasn't been negotiated_caps yet */ + if (GST_VIDEO_INFO_FORMAT (&pad->info) == GST_VIDEO_FORMAT_UNKNOWN) + continue; + + /* Convert to per-view width/height for unpacked forms */ + gst_video_multiview_video_info_change_mode (&tmp, + GST_VIDEO_MULTIVIEW_MODE_SEPARATED, GST_VIDEO_MULTIVIEW_FLAGS_NONE); + + this_width = GST_VIDEO_INFO_WIDTH (&tmp); + this_height = GST_VIDEO_INFO_HEIGHT (&tmp); + fps_n = GST_VIDEO_INFO_FPS_N (&tmp); + fps_d = GST_VIDEO_INFO_FPS_D (&tmp); + + GST_INFO_OBJECT (vagg, "Input pad %" GST_PTR_FORMAT + " w %u h %u", pad, this_width, this_height); + + if (this_width == 0 || this_height == 0) + continue; + + if (best_width < this_width) + best_width = this_width; + if (best_height < this_height) + best_height = this_height; + + if (fps_d == 0) + cur_fps = 0.0; + else + gst_util_fraction_to_double (fps_n, fps_d, &cur_fps); + + if (best_fps < cur_fps) { + best_fps = cur_fps; + best_fps_n = fps_n; + best_fps_d = fps_d; + } + + /* FIXME: Preserve PAR for at least one input when different sized inputs */ + } + GST_OBJECT_UNLOCK (vagg); + + mix_info = &mix->mix_info; + gst_video_info_set_format (mix_info, GST_VIDEO_FORMAT_RGBA, best_width, + best_height); + + GST_VIDEO_INFO_FPS_N (mix_info) = best_fps_n; + GST_VIDEO_INFO_FPS_D (mix_info) = best_fps_d; + + GST_VIDEO_INFO_MULTIVIEW_MODE (mix_info) = GST_VIDEO_MULTIVIEW_MODE_SEPARATED; + GST_VIDEO_INFO_VIEWS (mix_info) = 2; + + /* FIXME: If input is marked as flipped or flopped, preserve those flags */ + GST_VIDEO_INFO_MULTIVIEW_FLAGS (mix_info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE; + + /* Choose our output format based on downstream preferences */ + blend_caps = gst_video_info_to_caps (mix_info); + + gst_caps_set_features (blend_caps, 0, + gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); + + tmp_caps = get_converted_caps (GST_GL_STEREO_MIX (vagg), blend_caps); + gst_caps_unref (blend_caps); + + out_caps = gst_caps_intersect (caps, tmp_caps); + gst_caps_unref (tmp_caps); + + GST_DEBUG_OBJECT (vagg, "Possible output caps %" GST_PTR_FORMAT, out_caps); + + return out_caps; } /* Called after videoaggregator fixates our caps */ @@ -462,8 +540,6 @@ _negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps) return FALSE; /* Update the glview_convert output */ - if (!gst_video_info_from_caps (&mix->out_info, caps)) - return FALSE; /* We can configure the view_converter now */ gst_gl_view_convert_set_context (mix->viewconvert, @@ -585,108 +661,3 @@ gst_gl_stereo_mix_process_frames (GstGLStereoMix * mixer) return TRUE; } - -/* Iterate the input sink pads, and choose the blend format - * we will generate before output conversion, which is RGBA - * at some suitable size */ -static void -gst_gl_stereo_mix_find_best_format (GstVideoAggregator * vagg, - GstCaps * downstream_caps, GstVideoInfo * best_info, - gboolean * at_least_one_alpha) -{ - GstGLStereoMix *mix = GST_GL_STEREO_MIX (vagg); - GList *l; - gint best_width = -1, best_height = -1; - gdouble best_fps = -1, cur_fps; - gint best_fps_n = 0, best_fps_d = 1; - GstVideoInfo *mix_info; - GstCaps *blend_caps, *tmp_caps; - - /* We'll deal with alpha internally, so just tell aggregator to - * be quiet */ - *at_least_one_alpha = FALSE; - - GST_OBJECT_LOCK (vagg); - - for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { - GstVideoAggregatorPad *pad = l->data; - GstVideoInfo tmp = pad->info; - gint this_width, this_height; - gint fps_n, fps_d; - - if (!pad->info.finfo) - continue; - - /* This can happen if we release a pad and another pad hasn't been negotiated_caps yet */ - if (GST_VIDEO_INFO_FORMAT (&pad->info) == GST_VIDEO_FORMAT_UNKNOWN) - continue; - - /* Convert to per-view width/height for unpacked forms */ - gst_video_multiview_video_info_change_mode (&tmp, - GST_VIDEO_MULTIVIEW_MODE_SEPARATED, GST_VIDEO_MULTIVIEW_FLAGS_NONE); - - this_width = GST_VIDEO_INFO_WIDTH (&tmp); - this_height = GST_VIDEO_INFO_HEIGHT (&tmp); - fps_n = GST_VIDEO_INFO_FPS_N (&tmp); - fps_d = GST_VIDEO_INFO_FPS_D (&tmp); - - GST_INFO_OBJECT (vagg, "Input pad %" GST_PTR_FORMAT - " w %u h %u", pad, this_width, this_height); - - if (this_width == 0 || this_height == 0) - continue; - - if (best_width < this_width) - best_width = this_width; - if (best_height < this_height) - best_height = this_height; - - if (fps_d == 0) - cur_fps = 0.0; - else - gst_util_fraction_to_double (fps_n, fps_d, &cur_fps); - - if (best_fps < cur_fps) { - best_fps = cur_fps; - best_fps_n = fps_n; - best_fps_d = fps_d; - } - - /* FIXME: Preserve PAR for at least one input when different sized inputs */ - } - GST_OBJECT_UNLOCK (vagg); - - mix_info = &mix->mix_info; - gst_video_info_set_format (mix_info, GST_VIDEO_FORMAT_RGBA, best_width, - best_height); - - GST_VIDEO_INFO_FPS_N (mix_info) = best_fps_n; - GST_VIDEO_INFO_FPS_D (mix_info) = best_fps_d; - - GST_VIDEO_INFO_MULTIVIEW_MODE (mix_info) = GST_VIDEO_MULTIVIEW_MODE_SEPARATED; - GST_VIDEO_INFO_VIEWS (mix_info) = 2; - - /* FIXME: If input is marked as flipped or flopped, preserve those flags */ - GST_VIDEO_INFO_MULTIVIEW_FLAGS (mix_info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE; - - /* Choose our output format based on downstream preferences */ - blend_caps = gst_video_info_to_caps (mix_info); - - gst_caps_set_features (blend_caps, 0, - gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY)); - - tmp_caps = get_converted_caps (GST_GL_STEREO_MIX (vagg), blend_caps); - gst_caps_unref (blend_caps); - - if (mix->out_caps) - gst_caps_unref (mix->out_caps); - - mix->out_caps = gst_caps_intersect (downstream_caps, tmp_caps); - gst_caps_unref (tmp_caps); - - GST_DEBUG_OBJECT (vagg, "Possible output caps %" GST_PTR_FORMAT, - mix->out_caps); - /* Tell videoaggregator our preferred size. Actual info gets - * overridden during caps nego */ - *best_info = *mix_info; -} diff --git a/ext/gl/gstglstereomix.h b/ext/gl/gstglstereomix.h index b0f1bd232c..9971a89101 100644 --- a/ext/gl/gstglstereomix.h +++ b/ext/gl/gstglstereomix.h @@ -69,9 +69,6 @@ struct _GstGLStereoMix GstGLViewConvert *viewconvert; GstGLStereoDownmix downmix_mode; - GstCaps *out_caps; - GstVideoInfo out_info; - GstVideoInfo mix_info; GPtrArray *input_frames;