gtk: implement pixel and display aspect ratio handling
authorMatthew Waters <matthew@centricular.com>
Mon, 15 Jun 2015 08:28:37 +0000 (18:28 +1000)
committerMatthew Waters <matthew@centricular.com>
Mon, 15 Jun 2015 12:39:07 +0000 (22:39 +1000)
ext/gtk/gstgtkglsink.c
ext/gtk/gstgtkglsink.h
ext/gtk/gstgtksink.c
ext/gtk/gstgtksink.h
ext/gtk/gtkgstglwidget.c
ext/gtk/gtkgstwidget.c

index 372846f..660bf03 100644 (file)
@@ -33,6 +33,8 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_gl_sink);
 #define GST_CAT_DEFAULT gst_debug_gtk_gl_sink
 
 #define DEFAULT_FORCE_ASPECT_RATIO  TRUE
+#define DEFAULT_PAR_N               0
+#define DEFAULT_PAR_D               1
 
 static void gst_gtk_gl_sink_finalize (GObject * object);
 static void gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
@@ -67,6 +69,7 @@ enum
   PROP_0,
   PROP_WIDGET,
   PROP_FORCE_ASPECT_RATIO,
+  PROP_PIXEL_ASPECT_RATIO,
 };
 
 enum
@@ -112,6 +115,11 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
           DEFAULT_FORCE_ASPECT_RATIO,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
+      gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
+          "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
+          G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_gtk_gl_sink_template));
 
@@ -131,6 +139,8 @@ static void
 gst_gtk_gl_sink_init (GstGtkGLSink * gtk_sink)
 {
   gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+  gtk_sink->par_n = DEFAULT_PAR_N;
+  gtk_sink->par_d = DEFAULT_PAR_D;
 }
 
 static void
@@ -157,9 +167,12 @@ gst_gtk_gl_sink_get_widget (GstGtkGLSink * gtk_sink)
   }
 
   gtk_sink->widget = (GtkGstGLWidget *) gtk_gst_gl_widget_new ();
-  gtk_sink->bind_aspect_ratio =
+  gtk_sink->bind_force_aspect_ratio =
       g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget,
       "force-aspect-ratio", G_BINDING_BIDIRECTIONAL);
+  gtk_sink->bind_pixel_aspect_ratio =
+      g_object_bind_property (gtk_sink, "pixel-aspect-ratio", gtk_sink->widget,
+      "pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL);
 
   /* Take the floating ref, otherwise the destruction of the container will
    * make this widget disapear possibly before we are done. */
@@ -183,6 +196,9 @@ gst_gtk_gl_sink_get_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       g_value_set_boolean (value, gtk_sink->force_aspect_ratio);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gst_value_set_fraction (value, gtk_sink->par_n, gtk_sink->par_d);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -199,6 +215,10 @@ gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       gtk_sink->force_aspect_ratio = g_value_get_boolean (value);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gtk_sink->par_n = gst_value_get_fraction_numerator (value);
+      gtk_sink->par_d = gst_value_get_fraction_denominator (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 4c13059..eaf2f0c 100644 (file)
@@ -67,7 +67,11 @@ struct _GstGtkGLSink
 
   /* properties */
   gboolean              force_aspect_ratio;
-  GBinding             *bind_aspect_ratio;
+  GBinding             *bind_force_aspect_ratio;
+
+  gint                  par_n;
+  gint                  par_d;
+  GBinding             *bind_pixel_aspect_ratio;
 
   GstGtkGLSinkPrivate  *priv;
 };
index 1b34956..67fe7de 100644 (file)
@@ -59,12 +59,15 @@ GST_STATIC_PAD_TEMPLATE ("sink",
     );
 
 #define DEFAULT_FORCE_ASPECT_RATIO  TRUE
+#define DEFAULT_PAR_N               0
+#define DEFAULT_PAR_D               1
 
 enum
 {
   PROP_0,
   PROP_WIDGET,
   PROP_FORCE_ASPECT_RATIO,
+  PROP_PIXEL_ASPECT_RATIO,
 };
 
 enum
@@ -110,6 +113,11 @@ gst_gtk_sink_class_init (GstGtkSinkClass * klass)
           DEFAULT_FORCE_ASPECT_RATIO,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
+      gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
+          "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
+          G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&gst_gtk_sink_template));
 
@@ -127,6 +135,9 @@ gst_gtk_sink_class_init (GstGtkSinkClass * klass)
 static void
 gst_gtk_sink_init (GstGtkSink * gtk_sink)
 {
+  gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+  gtk_sink->par_n = DEFAULT_PAR_N;
+  gtk_sink->par_d = DEFAULT_PAR_D;
 }
 
 static void
@@ -156,6 +167,9 @@ gst_gtk_sink_get_widget (GstGtkSink * gtk_sink)
   gtk_sink->bind_aspect_ratio =
       g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget,
       "force-aspect-ratio", G_BINDING_BIDIRECTIONAL);
+  gtk_sink->bind_pixel_aspect_ratio =
+      g_object_bind_property (gtk_sink, "pixel-aspect-ratio", gtk_sink->widget,
+      "pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL);
 
   /* Take the floating ref, other wise the destruction of the container will
    * make this widget disapear possibly before we are done. */
@@ -177,6 +191,9 @@ gst_gtk_sink_get_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       g_value_set_boolean (value, gtk_sink->force_aspect_ratio);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gst_value_set_fraction (value, gtk_sink->par_n, gtk_sink->par_d);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -193,6 +210,10 @@ gst_gtk_sink_set_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       gtk_sink->force_aspect_ratio = g_value_get_boolean (value);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gtk_sink->par_n = gst_value_get_fraction_numerator (value);
+      gtk_sink->par_d = gst_value_get_fraction_denominator (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 444c4b1..d3e0b7b 100644 (file)
@@ -60,6 +60,10 @@ struct _GstGtkSink
   gboolean             force_aspect_ratio;
   GBinding             *bind_aspect_ratio;
 
+  gint                  par_n;
+  gint                  par_d;
+  GBinding             *bind_pixel_aspect_ratio;
+
   GstGtkSinkPrivate   *priv;
 };
 
index ba68ba3..26fa0dc 100644 (file)
@@ -51,18 +51,20 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
 G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA,
     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstglwidget", 0,
-        "Gtk Gst GL Widget");
-    );
+        "Gtk Gst GL Widget"););
 
 #define GTK_GST_GL_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
     GTK_TYPE_GST_GL_WIDGET, GtkGstGLWidgetPrivate))
 
 #define DEFAULT_FORCE_ASPECT_RATIO  TRUE
+#define DEFAULT_PAR_N               0
+#define DEFAULT_PAR_D               1
 
 enum
 {
   PROP_0,
   PROP_FORCE_ASPECT_RATIO,
+  PROP_PIXEL_ASPECT_RATIO,
 };
 
 struct _GtkGstGLWidgetPrivate
@@ -71,6 +73,10 @@ struct _GtkGstGLWidgetPrivate
 
   /* properties */
   gboolean force_aspect_ratio;
+  gint par_n, par_d;
+
+  gint display_width;
+  gint display_height;
 
   gboolean negotiated;
   GstBuffer *buffer;
@@ -210,8 +216,8 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
 
     src.x = 0;
     src.y = 0;
-    src.w = GST_VIDEO_INFO_WIDTH (&gst_widget->priv->v_info);
-    src.h = GST_VIDEO_INFO_HEIGHT (&gst_widget->priv->v_info);
+    src.w = gst_widget->priv->display_width;
+    src.h = gst_widget->priv->display_height;
 
     dst.x = gtk_viewport[0];
     dst.y = gtk_viewport[1];
@@ -442,6 +448,10 @@ gtk_gst_gl_widget_set_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       gtk_widget->priv->force_aspect_ratio = g_value_get_boolean (value);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gtk_widget->priv->par_n = gst_value_get_fraction_numerator (value);
+      gtk_widget->priv->par_d = gst_value_get_fraction_denominator (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -458,6 +468,10 @@ gtk_gst_gl_widget_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_FORCE_ASPECT_RATIO:
       g_value_set_boolean (value, gtk_widget->priv->force_aspect_ratio);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gst_value_set_fraction (value, gtk_widget->priv->par_n,
+          gtk_widget->priv->par_d);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -484,6 +498,11 @@ gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass)
           DEFAULT_FORCE_ASPECT_RATIO,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_klass, PROP_PIXEL_ASPECT_RATIO,
+      gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
+          "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
+          G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gl_widget_klass->render = gtk_gst_gl_widget_render;
 
   widget_klass->get_preferred_width = gtk_gst_gl_widget_get_preferred_width;
@@ -498,6 +517,8 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * widget)
   widget->priv = GTK_GST_GL_WIDGET_GET_PRIVATE (widget);
 
   widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+  widget->priv->par_n = DEFAULT_PAR_N;
+  widget->priv->par_d = DEFAULT_PAR_D;
 
   g_mutex_init (&widget->priv->lock);
 
@@ -523,7 +544,7 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * widget)
   if (!widget->priv->display)
     widget->priv->display = gst_gl_display_new ();
 
-  gtk_gl_area_set_has_alpha ((GtkGLArea *) widget, TRUE);
+  gtk_gl_area_set_has_alpha ((GtkGLArea *) widget, FALSE);
 }
 
 GtkWidget *
@@ -665,6 +686,66 @@ gtk_gst_gl_widget_init_winsys (GtkGstGLWidget * widget)
   return TRUE;
 }
 
+static gboolean
+_calculate_par (GtkGstGLWidget * widget, GstVideoInfo * info)
+{
+  gboolean ok;
+  gint width, height;
+  gint par_n, par_d;
+  gint display_par_n, display_par_d;
+  guint display_ratio_num, display_ratio_den;
+
+  width = GST_VIDEO_INFO_WIDTH (info);
+  height = GST_VIDEO_INFO_HEIGHT (info);
+
+  par_n = GST_VIDEO_INFO_PAR_N (info);
+  par_d = GST_VIDEO_INFO_PAR_D (info);
+
+  if (!par_n)
+    par_n = 1;
+
+  /* get display's PAR */
+  if (widget->priv->par_n != 0 && widget->priv->par_d != 0) {
+    display_par_n = widget->priv->par_n;
+    display_par_d = widget->priv->par_d;
+  } else {
+    display_par_n = 1;
+    display_par_d = 1;
+  }
+
+  ok = gst_video_calculate_display_ratio (&display_ratio_num,
+      &display_ratio_den, width, height, par_n, par_d, display_par_n,
+      display_par_d);
+
+  if (!ok)
+    return FALSE;
+
+  GST_LOG ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, display_par_d);
+
+  if (height % display_ratio_den == 0) {
+    GST_DEBUG ("keeping video height");
+    widget->priv->display_width = (guint)
+        gst_util_uint64_scale_int (height, display_ratio_num,
+        display_ratio_den);
+    widget->priv->display_height = height;
+  } else if (width % display_ratio_num == 0) {
+    GST_DEBUG ("keeping video width");
+    widget->priv->display_width = width;
+    widget->priv->display_height = (guint)
+        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
+  } else {
+    GST_DEBUG ("approximating while keeping video height");
+    widget->priv->display_width = (guint)
+        gst_util_uint64_scale_int (height, display_ratio_num,
+        display_ratio_den);
+    widget->priv->display_height = height;
+  }
+  GST_DEBUG ("scaling to %dx%d", widget->priv->display_width,
+      widget->priv->display_height);
+
+  return TRUE;
+}
+
 gboolean
 gtk_gst_gl_widget_set_caps (GtkGstGLWidget * widget, GstCaps * caps)
 {
@@ -691,6 +772,11 @@ gtk_gst_gl_widget_set_caps (GtkGstGLWidget * widget, GstCaps * caps)
   gst_caps_set_features (widget->priv->gl_caps, 0,
       gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY));
 
+  if (!_calculate_par (widget, &v_info)) {
+    g_mutex_unlock (&widget->priv->lock);
+    return FALSE;
+  }
+
   widget->priv->v_info = v_info;
   widget->priv->negotiated = TRUE;
 
index aa40f39..7607bd5 100644 (file)
@@ -41,11 +41,14 @@ G_DEFINE_TYPE (GtkGstWidget, gtk_gst_widget, GTK_TYPE_DRAWING_AREA);
     GTK_TYPE_GST_WIDGET, GtkGstWidgetPrivate))
 
 #define DEFAULT_FORCE_ASPECT_RATIO  TRUE
+#define DEFAULT_PAR_N               0
+#define DEFAULT_PAR_D               1
 
 enum
 {
   PROP_0,
   PROP_FORCE_ASPECT_RATIO,
+  PROP_PIXEL_ASPECT_RATIO,
 };
 
 struct _GtkGstWidgetPrivate
@@ -54,6 +57,10 @@ struct _GtkGstWidgetPrivate
 
   /* properties */
   gboolean force_aspect_ratio;
+  gint par_n, par_d;
+
+  gint display_width;
+  gint display_height;
 
   gboolean negotiated;
   GstBuffer *buffer;
@@ -110,10 +117,9 @@ gtk_gst_widget_draw (GtkWidget * widget, cairo_t * cr)
   if (gst_widget->priv->negotiated && gst_widget->priv->buffer
       && gst_video_frame_map (&frame, &gst_widget->priv->v_info,
           gst_widget->priv->buffer, GST_MAP_READ)) {
-    gdouble scale_x =
-        (gdouble) widget_width / GST_VIDEO_INFO_WIDTH (&frame.info);
+    gdouble scale_x = (gdouble) widget_width / gst_widget->priv->display_width;
     gdouble scale_y =
-        (gdouble) widget_height / GST_VIDEO_INFO_HEIGHT (&frame.info);
+        (gdouble) widget_height / gst_widget->priv->display_height;
     GstVideoRectangle result;
 
     gst_widget->priv->v_info = frame.info;
@@ -127,8 +133,8 @@ gtk_gst_widget_draw (GtkWidget * widget, cairo_t * cr)
 
       src.x = 0;
       src.y = 0;
-      src.w = GST_VIDEO_INFO_WIDTH (&frame.info);
-      src.h = GST_VIDEO_INFO_HEIGHT (&frame.info);
+      src.w = gst_widget->priv->display_width;
+      src.h = gst_widget->priv->display_height;
 
       dst.x = 0;
       dst.y = 0;
@@ -145,6 +151,12 @@ gtk_gst_widget_draw (GtkWidget * widget, cairo_t * cr)
       result.h = widget_height;
     }
 
+    scale_x *=
+        (gdouble) gst_widget->priv->display_width / (gdouble) frame.info.width;
+    scale_y *=
+        (gdouble) gst_widget->priv->display_height /
+        (gdouble) frame.info.height;
+
     cairo_translate (cr, result.x, result.y);
     cairo_scale (cr, scale_x, scale_y);
     cairo_rectangle (cr, 0, 0, result.w, result.h);
@@ -189,6 +201,10 @@ gtk_gst_widget_set_property (GObject * object, guint prop_id,
     case PROP_FORCE_ASPECT_RATIO:
       gtk_widget->priv->force_aspect_ratio = g_value_get_boolean (value);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gtk_widget->priv->par_n = gst_value_get_fraction_numerator (value);
+      gtk_widget->priv->par_d = gst_value_get_fraction_denominator (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -205,6 +221,10 @@ gtk_gst_widget_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_FORCE_ASPECT_RATIO:
       g_value_set_boolean (value, gtk_widget->priv->force_aspect_ratio);
       break;
+    case PROP_PIXEL_ASPECT_RATIO:
+      gst_value_set_fraction (value, gtk_widget->priv->par_n,
+          gtk_widget->priv->par_d);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -230,6 +250,11 @@ gtk_gst_widget_class_init (GtkGstWidgetClass * klass)
           DEFAULT_FORCE_ASPECT_RATIO,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_klass, PROP_PIXEL_ASPECT_RATIO,
+      gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
+          "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
+          G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   widget_klass->draw = gtk_gst_widget_draw;
   widget_klass->get_preferred_width = gtk_gst_widget_get_preferred_width;
   widget_klass->get_preferred_height = gtk_gst_widget_get_preferred_height;
@@ -241,6 +266,8 @@ gtk_gst_widget_init (GtkGstWidget * widget)
   widget->priv = GTK_GST_WIDGET_GET_PRIVATE (widget);
 
   widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+  widget->priv->par_n = DEFAULT_PAR_N;
+  widget->priv->par_d = DEFAULT_PAR_D;
 
   g_mutex_init (&widget->priv->lock);
 }
@@ -284,6 +311,66 @@ _queue_resize (GtkGstWidget * widget)
   return G_SOURCE_REMOVE;
 }
 
+static gboolean
+_calculate_par (GtkGstWidget * widget, GstVideoInfo * info)
+{
+  gboolean ok;
+  gint width, height;
+  gint par_n, par_d;
+  gint display_par_n, display_par_d;
+  guint display_ratio_num, display_ratio_den;
+
+  width = GST_VIDEO_INFO_WIDTH (info);
+  height = GST_VIDEO_INFO_HEIGHT (info);
+
+  par_n = GST_VIDEO_INFO_PAR_N (info);
+  par_d = GST_VIDEO_INFO_PAR_D (info);
+
+  if (!par_n)
+    par_n = 1;
+
+  /* get display's PAR */
+  if (widget->priv->par_n != 0 && widget->priv->par_d != 0) {
+    display_par_n = widget->priv->par_n;
+    display_par_d = widget->priv->par_d;
+  } else {
+    display_par_n = 1;
+    display_par_d = 1;
+  }
+
+  ok = gst_video_calculate_display_ratio (&display_ratio_num,
+      &display_ratio_den, width, height, par_n, par_d, display_par_n,
+      display_par_d);
+
+  if (!ok)
+    return FALSE;
+
+  GST_LOG ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, display_par_d);
+
+  if (height % display_ratio_den == 0) {
+    GST_DEBUG ("keeping video height");
+    widget->priv->display_width = (guint)
+        gst_util_uint64_scale_int (height, display_ratio_num,
+        display_ratio_den);
+    widget->priv->display_height = height;
+  } else if (width % display_ratio_num == 0) {
+    GST_DEBUG ("keeping video width");
+    widget->priv->display_width = width;
+    widget->priv->display_height = (guint)
+        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
+  } else {
+    GST_DEBUG ("approximating while keeping video height");
+    widget->priv->display_width = (guint)
+        gst_util_uint64_scale_int (height, display_ratio_num,
+        display_ratio_den);
+    widget->priv->display_height = height;
+  }
+  GST_DEBUG ("scaling to %dx%d", widget->priv->display_width,
+      widget->priv->display_height);
+
+  return TRUE;
+}
+
 gboolean
 gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps)
 {
@@ -306,6 +393,11 @@ gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps)
 
   g_mutex_lock (&widget->priv->lock);
 
+  if (!_calculate_par (widget, &v_info)) {
+    g_mutex_unlock (&widget->priv->lock);
+    return FALSE;
+  }
+
   gst_caps_replace (&widget->priv->caps, caps);
   widget->priv->v_info = v_info;
   widget->priv->negotiated = TRUE;