Commit 612ee008 authored by Matthew Waters's avatar Matthew Waters 🐨 Committed by Tim-Philipp Müller

glvideoflip: correctly update the output caps on method changes

When changing methods we may need different output caps.
parent 62588100
......@@ -103,6 +103,7 @@ G_DEFINE_TYPE_WITH_CODE (GstGLVideoFlip, gst_gl_video_flip,
GST_TYPE_BIN, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
"glvideoflip", 0, "glvideoflip element"););
static void gst_gl_video_flip_finalize (GObject * object);
static void gst_gl_video_flip_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_gl_video_flip_get_property (GObject * object, guint prop_id,
......@@ -122,6 +123,7 @@ gst_gl_video_flip_class_init (GstGLVideoFlipClass * klass)
gobject_class = (GObjectClass *) klass;
element_class = GST_ELEMENT_CLASS (klass);
gobject_class->finalize = gst_gl_video_flip_finalize;
gobject_class->set_property = gst_gl_video_flip_set_property;
gobject_class->get_property = gst_gl_video_flip_get_property;
......@@ -201,11 +203,79 @@ gst_gl_video_flip_init (GstGLVideoFlip * flip)
}
}
static void
gst_gl_video_flip_finalize (GObject * object)
{
GstGLVideoFlip *flip = GST_GL_VIDEO_FLIP (object);
gst_caps_replace (&flip->input_caps, NULL);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/* Caps negotiation happens like this:
*
* 1. caps/accept-caps queries bypass the capsfilters on either side of the
* transformation element so the fixed caps don't get in the way.
* 2. Receiving a caps event on the sink pad will set fixed caps on either side
* of the transformation element.
*/
static GstCaps *
_transform_caps (GstGLVideoFlip * vf, GstPadDirection direction, GstCaps * caps)
{
GstCaps *output = gst_caps_copy (caps);
gint i;
for (i = 0; i < gst_caps_get_size (output); i++) {
GstStructure *structure = gst_caps_get_structure (output, i);
gint width, height;
gint par_n, par_d;
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "height", &height)) {
switch (vf->active_method) {
case GST_GL_VIDEO_FLIP_METHOD_90R:
case GST_GL_VIDEO_FLIP_METHOD_90L:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_UL_LR:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_UR_LL:
gst_structure_set (structure, "width", G_TYPE_INT, height,
"height", G_TYPE_INT, width, NULL);
if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
&par_n, &par_d)) {
if (par_n != 1 || par_d != 1) {
GValue val = { 0, };
g_value_init (&val, GST_TYPE_FRACTION);
gst_value_set_fraction (&val, par_d, par_n);
gst_structure_set_value (structure, "pixel-aspect-ratio", &val);
g_value_unset (&val);
}
}
break;
case GST_GL_VIDEO_FLIP_METHOD_IDENTITY:
case GST_GL_VIDEO_FLIP_METHOD_180:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_HORIZ:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_VERT:
break;
default:
g_assert_not_reached ();
break;
}
}
}
return output;
}
/* with object lock */
static void
_set_active_method (GstGLVideoFlip * vf, GstGLVideoFlipMethod method)
_set_active_method (GstGLVideoFlip * vf, GstGLVideoFlipMethod method,
GstCaps * caps)
{
gfloat rot_z = 0., scale_x = 1.0, scale_y = 1.0;
GstCaps *output_caps, *templ;
GstPad *srcpad;
switch (method) {
case GST_GL_VIDEO_FLIP_METHOD_IDENTITY:
......@@ -244,7 +314,19 @@ _set_active_method (GstGLVideoFlip * vf, GstGLVideoFlipMethod method)
break;
}
vf->active_method = method;
output_caps = _transform_caps (vf, GST_PAD_SINK, caps);
gst_caps_replace (&vf->input_caps, caps);
srcpad = gst_element_get_static_pad (vf->transformation, "src");
templ = gst_pad_get_pad_template_caps (srcpad);
gst_object_unref (srcpad);
gst_caps_append (output_caps, gst_caps_ref (templ));
GST_OBJECT_UNLOCK (vf);
g_object_set (vf->input_capsfilter, "caps", gst_caps_ref (caps), NULL);
g_object_set (vf->output_capsfilter, "caps", output_caps, NULL);
g_object_set (vf->transformation, "rotation-z", rot_z, "scale-x", scale_x,
"scale-y", scale_y, NULL);
GST_OBJECT_LOCK (vf);
......@@ -267,7 +349,8 @@ gst_gl_video_flip_set_method (GstGLVideoFlip * vf, GstGLVideoFlipMethod method,
else
method = vf->method;
_set_active_method (vf, method);
if (vf->input_caps)
_set_active_method (vf, method, vf->input_caps);
GST_OBJECT_UNLOCK (vf);
}
......@@ -304,61 +387,6 @@ gst_gl_video_flip_get_property (GObject * object, guint prop_id,
}
}
/* Caps negotiation happens like this:
*
* 1. caps/accept-caps queries bypass the capsfilters on either side of the
* transformation element so the fixed caps don't get in the way.
* 2. Receiving a caps event on the sink pad will set fixed caps on either side
* of the transformation element.
*/
static GstCaps *
_transform_caps (GstGLVideoFlip * vf, GstPadDirection direction, GstCaps * caps)
{
GstCaps *output = gst_caps_copy (caps);
gint i;
for (i = 0; i < gst_caps_get_size (output); i++) {
GstStructure *structure = gst_caps_get_structure (output, i);
gint width, height;
gint par_n, par_d;
if (gst_structure_get_int (structure, "width", &width) &&
gst_structure_get_int (structure, "height", &height)) {
switch (vf->active_method) {
case GST_GL_VIDEO_FLIP_METHOD_90R:
case GST_GL_VIDEO_FLIP_METHOD_90L:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_UL_LR:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_UR_LL:
gst_structure_set (structure, "width", G_TYPE_INT, height,
"height", G_TYPE_INT, width, NULL);
if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
&par_n, &par_d)) {
if (par_n != 1 || par_d != 1) {
GValue val = { 0, };
g_value_init (&val, GST_TYPE_FRACTION);
gst_value_set_fraction (&val, par_d, par_n);
gst_structure_set_value (structure, "pixel-aspect-ratio", &val);
g_value_unset (&val);
}
}
break;
case GST_GL_VIDEO_FLIP_METHOD_IDENTITY:
case GST_GL_VIDEO_FLIP_METHOD_180:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_HORIZ:
case GST_GL_VIDEO_FLIP_METHOD_FLIP_VERT:
break;
default:
g_assert_not_reached ();
break;
}
}
}
return output;
}
static GstPadProbeReturn
_input_sink_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
......@@ -406,8 +434,7 @@ _input_sink_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
break;
}
case GST_EVENT_CAPS:{
GstCaps *caps, *output, *templ;
GstPad *srcpad;
GstCaps *caps;
GstVideoInfo v_info;
gst_event_parse_caps (event, &caps);
......@@ -418,19 +445,8 @@ _input_sink_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
(gfloat) GST_VIDEO_INFO_HEIGHT (&v_info);
else
vf->aspect = 1.0;
_set_active_method (vf, vf->active_method);
_set_active_method (vf, vf->active_method, caps);
GST_OBJECT_UNLOCK (vf);
output = _transform_caps (vf, GST_PAD_SINK, caps);
/* allow overriding the output caps */
srcpad = gst_element_get_static_pad (vf->transformation, "src");
templ = gst_pad_get_pad_template_caps (srcpad);
gst_caps_append (output, gst_caps_ref (templ));
gst_object_unref (srcpad);
g_object_set (vf->input_capsfilter, "caps", gst_caps_copy (caps), NULL);
g_object_set (vf->output_capsfilter, "caps", output, NULL);
break;
}
default:
......
......@@ -75,6 +75,8 @@ struct _GstGLVideoFlip
gulong sink_probe;
gulong src_probe;
GstCaps *input_caps;
/* properties */
GstGLVideoFlipMethod method;
GstGLVideoFlipMethod tag_method;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment