summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2015-06-12 15:17:30 +1000
committerMatthew Waters <matthew@centricular.com>2015-06-12 15:17:30 +1000
commitb97f2e6e6a7868e8ded4fd197445b257256a8c9c (patch)
treea235061c07d55371ec248d06d6f0f0ccafb9c3f9
parentea4867dfa71fccc0b10c418dd7f02910abeb13fe (diff)
downloadgstreamer-plugins-bad-b97f2e6e6a7868e8ded4fd197445b257256a8c9c.tar.gz
gtk: implement video aspect-ratio handling
For both the software and the GL sink's. Doesn't deal with the pixel-aspect-ratio field at all yet.
-rw-r--r--ext/gtk/gstgtkglsink.c48
-rw-r--r--ext/gtk/gstgtkglsink.h4
-rw-r--r--ext/gtk/gstgtksink.c51
-rw-r--r--ext/gtk/gstgtksink.h4
-rw-r--r--ext/gtk/gtkgstglwidget.c84
-rw-r--r--ext/gtk/gtkgstwidget.c86
6 files changed, 243 insertions, 34 deletions
diff --git a/ext/gtk/gstgtkglsink.c b/ext/gtk/gstgtkglsink.c
index c89c940eb..372846f0e 100644
--- a/ext/gtk/gstgtkglsink.c
+++ b/ext/gtk/gstgtkglsink.c
@@ -32,6 +32,8 @@
GST_DEBUG_CATEGORY (gst_debug_gtk_gl_sink);
#define GST_CAT_DEFAULT gst_debug_gtk_gl_sink
+#define DEFAULT_FORCE_ASPECT_RATIO TRUE
+
static void gst_gtk_gl_sink_finalize (GObject * object);
static void gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * param_spec);
@@ -62,8 +64,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
enum
{
- ARG_0,
- PROP_WIDGET
+ PROP_0,
+ PROP_WIDGET,
+ PROP_FORCE_ASPECT_RATIO,
};
enum
@@ -102,6 +105,13 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
"The GtkWidget to place in the widget heirachy",
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean ("force-aspect-ratio",
+ "Force aspect ratio",
+ "When enabled, scaling will respect original aspect ratio",
+ DEFAULT_FORCE_ASPECT_RATIO,
+ 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));
@@ -120,17 +130,7 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
static void
gst_gtk_gl_sink_init (GstGtkGLSink * gtk_sink)
{
-}
-
-static void
-gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- switch (prop_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
}
static void
@@ -157,6 +157,9 @@ gst_gtk_gl_sink_get_widget (GstGtkGLSink * gtk_sink)
}
gtk_sink->widget = (GtkGstGLWidget *) gtk_gst_gl_widget_new ();
+ gtk_sink->bind_aspect_ratio =
+ g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget,
+ "force-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. */
@@ -177,6 +180,25 @@ gst_gtk_gl_sink_get_property (GObject * object, guint prop_id,
case PROP_WIDGET:
g_value_set_object (value, gst_gtk_gl_sink_get_widget (gtk_sink));
break;
+ case PROP_FORCE_ASPECT_RATIO:
+ g_value_set_boolean (value, gtk_sink->force_aspect_ratio);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstGtkGLSink *gtk_sink = GST_GTK_GL_SINK (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ gtk_sink->force_aspect_ratio = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/ext/gtk/gstgtkglsink.h b/ext/gtk/gstgtkglsink.h
index 145726058..4c13059f5 100644
--- a/ext/gtk/gstgtkglsink.h
+++ b/ext/gtk/gstgtkglsink.h
@@ -65,6 +65,10 @@ struct _GstGtkGLSink
GstGLUpload *upload;
GstBuffer *uploaded_buffer;
+ /* properties */
+ gboolean force_aspect_ratio;
+ GBinding *bind_aspect_ratio;
+
GstGtkGLSinkPrivate *priv;
};
diff --git a/ext/gtk/gstgtksink.c b/ext/gtk/gstgtksink.c
index 94b704775..1b349561c 100644
--- a/ext/gtk/gstgtksink.c
+++ b/ext/gtk/gstgtksink.c
@@ -58,10 +58,13 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("BGRA"))
);
+#define DEFAULT_FORCE_ASPECT_RATIO TRUE
+
enum
{
- ARG_0,
- PROP_WIDGET
+ PROP_0,
+ PROP_WIDGET,
+ PROP_FORCE_ASPECT_RATIO,
};
enum
@@ -100,6 +103,13 @@ gst_gtk_sink_class_init (GstGtkSinkClass * klass)
"The GtkWidget to place in the widget heirachy",
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean ("force-aspect-ratio",
+ "Force aspect ratio",
+ "When enabled, scaling will respect original aspect ratio",
+ DEFAULT_FORCE_ASPECT_RATIO,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_gtk_sink_template));
@@ -120,17 +130,6 @@ gst_gtk_sink_init (GstGtkSink * gtk_sink)
}
static void
-gst_gtk_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- switch (prop_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
gst_gtk_sink_finalize (GObject * object)
{
GstGtkSink *gtk_sink = GST_GTK_SINK (object);;
@@ -154,6 +153,9 @@ gst_gtk_sink_get_widget (GstGtkSink * gtk_sink)
}
gtk_sink->widget = (GtkGstWidget *) gtk_gst_widget_new ();
+ gtk_sink->bind_aspect_ratio =
+ g_object_bind_property (gtk_sink, "force-aspect-ratio", gtk_sink->widget,
+ "force-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. */
@@ -166,14 +168,31 @@ static void
gst_gtk_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
- GstGtkSink *gtk_sink;
-
- gtk_sink = GST_GTK_SINK (object);
+ GstGtkSink *gtk_sink = GST_GTK_SINK (object);
switch (prop_id) {
case PROP_WIDGET:
g_value_set_object (value, gst_gtk_sink_get_widget (gtk_sink));
break;
+ case PROP_FORCE_ASPECT_RATIO:
+ g_value_set_boolean (value, gtk_sink->force_aspect_ratio);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_gtk_sink_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstGtkSink *gtk_sink = GST_GTK_SINK (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ gtk_sink->force_aspect_ratio = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/ext/gtk/gstgtksink.h b/ext/gtk/gstgtksink.h
index e8cdf48a5..444c4b198 100644
--- a/ext/gtk/gstgtksink.h
+++ b/ext/gtk/gstgtksink.h
@@ -56,6 +56,10 @@ struct _GstGtkSink
GtkGstWidget *widget;
+ /* properties */
+ gboolean force_aspect_ratio;
+ GBinding *bind_aspect_ratio;
+
GstGtkSinkPrivate *priv;
};
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 11c5b6f15..100fa1d07 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -51,10 +51,21 @@ G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA,
#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
+
+enum
+{
+ PROP_0,
+ PROP_FORCE_ASPECT_RATIO,
+};
+
struct _GtkGstGLWidgetPrivate
{
GMutex lock;
+ /* properties */
+ gboolean force_aspect_ratio;
+
gboolean negotiated;
GstBuffer *buffer;
GstCaps *gl_caps;
@@ -182,6 +193,30 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable;
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+ if (gst_widget->priv->force_aspect_ratio) {
+ GstVideoRectangle src, dst, result;
+ gint gtk_viewport[4];
+
+ gl->ClearColor (0.0, 0.0, 0.0, 0.0);
+ gl->Clear (GL_COLOR_BUFFER_BIT);
+
+ gl->GetIntegerv (GL_VIEWPORT, gtk_viewport);
+
+ 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);
+
+ dst.x = gtk_viewport[0];
+ dst.y = gtk_viewport[1];
+ dst.w = gtk_viewport[2];
+ dst.h = gtk_viewport[3];
+
+ gst_video_sink_center_rect (src, dst, &result, TRUE);
+
+ gl->Viewport (result.x, result.y, result.w, result.h);
+ }
+
gst_gl_shader_use (gst_widget->priv->shader);
if (gl->BindVertexArray)
@@ -391,18 +426,61 @@ gtk_gst_gl_widget_finalize (GObject * object)
}
static void
+gtk_gst_gl_widget_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GtkGstGLWidget *gtk_widget = GTK_GST_GL_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ gtk_widget->priv->force_aspect_ratio = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_gst_gl_widget_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GtkGstGLWidget *gtk_widget = GTK_GST_GL_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ g_value_set_boolean (value, gtk_widget->priv->force_aspect_ratio);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass)
{
+ GObjectClass *gobject_klass = (GObjectClass *) klass;
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
GtkGLAreaClass *gl_widget_klass = (GtkGLAreaClass *) klass;
g_type_class_add_private (klass, sizeof (GtkGstGLWidgetPrivate));
+ gobject_klass->set_property = gtk_gst_gl_widget_set_property;
+ gobject_klass->get_property = gtk_gst_gl_widget_get_property;
+ gobject_klass->finalize = gtk_gst_gl_widget_finalize;
+
+ g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean ("force-aspect-ratio",
+ "Force aspect ratio",
+ "When enabled, scaling will respect original aspect ratio",
+ DEFAULT_FORCE_ASPECT_RATIO,
+ 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;
widget_klass->get_preferred_height = gtk_gst_gl_widget_get_preferred_height;
-
- G_OBJECT_CLASS (klass)->finalize = gtk_gst_gl_widget_finalize;
}
static void
@@ -412,6 +490,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;
+
g_mutex_init (&widget->priv->lock);
display = gdk_display_get_default ();
diff --git a/ext/gtk/gtkgstwidget.c b/ext/gtk/gtkgstwidget.c
index c103df727..aa40f3939 100644
--- a/ext/gtk/gtkgstwidget.c
+++ b/ext/gtk/gtkgstwidget.c
@@ -40,10 +40,21 @@ G_DEFINE_TYPE (GtkGstWidget, gtk_gst_widget, GTK_TYPE_DRAWING_AREA);
#define GTK_GST_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
GTK_TYPE_GST_WIDGET, GtkGstWidgetPrivate))
+#define DEFAULT_FORCE_ASPECT_RATIO TRUE
+
+enum
+{
+ PROP_0,
+ PROP_FORCE_ASPECT_RATIO,
+};
+
struct _GtkGstWidgetPrivate
{
GMutex lock;
+ /* properties */
+ gboolean force_aspect_ratio;
+
gboolean negotiated;
GstBuffer *buffer;
GstCaps *caps;
@@ -103,6 +114,7 @@ gtk_gst_widget_draw (GtkWidget * widget, cairo_t * cr)
(gdouble) widget_width / GST_VIDEO_INFO_WIDTH (&frame.info);
gdouble scale_y =
(gdouble) widget_height / GST_VIDEO_INFO_HEIGHT (&frame.info);
+ GstVideoRectangle result;
gst_widget->priv->v_info = frame.info;
@@ -110,8 +122,32 @@ gtk_gst_widget_draw (GtkWidget * widget, cairo_t * cr)
CAIRO_FORMAT_ARGB32, frame.info.width, frame.info.height,
frame.info.stride[0]);
+ if (gst_widget->priv->force_aspect_ratio) {
+ GstVideoRectangle src, dst;
+
+ src.x = 0;
+ src.y = 0;
+ src.w = GST_VIDEO_INFO_WIDTH (&frame.info);
+ src.h = GST_VIDEO_INFO_HEIGHT (&frame.info);
+
+ dst.x = 0;
+ dst.y = 0;
+ dst.w = widget_width;
+ dst.h = widget_height;
+
+ gst_video_sink_center_rect (src, dst, &result, TRUE);
+
+ scale_x = scale_y = MIN (scale_x, scale_y);
+ } else {
+ result.x = 0;
+ result.y = 0;
+ result.w = widget_width;
+ result.h = widget_height;
+ }
+
+ cairo_translate (cr, result.x, result.y);
cairo_scale (cr, scale_x, scale_y);
- cairo_rectangle (cr, 0, 0, widget_width, widget_height);
+ cairo_rectangle (cr, 0, 0, result.w, result.h);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
@@ -144,17 +180,59 @@ gtk_gst_widget_finalize (GObject * object)
}
static void
+gtk_gst_widget_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GtkGstWidget *gtk_widget = GTK_GST_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ gtk_widget->priv->force_aspect_ratio = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_gst_widget_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GtkGstWidget *gtk_widget = GTK_GST_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_FORCE_ASPECT_RATIO:
+ g_value_set_boolean (value, gtk_widget->priv->force_aspect_ratio);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
gtk_gst_widget_class_init (GtkGstWidgetClass * klass)
{
+ GObjectClass *gobject_klass = (GObjectClass *) klass;
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
g_type_class_add_private (klass, sizeof (GtkGstWidgetPrivate));
+ gobject_klass->set_property = gtk_gst_widget_set_property;
+ gobject_klass->get_property = gtk_gst_widget_get_property;
+ gobject_klass->finalize = gtk_gst_widget_finalize;
+
+ g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean ("force-aspect-ratio",
+ "Force aspect ratio",
+ "When enabled, scaling will respect original aspect ratio",
+ DEFAULT_FORCE_ASPECT_RATIO,
+ 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;
-
- G_OBJECT_CLASS (klass)->finalize = gtk_gst_widget_finalize;
}
static void
@@ -162,6 +240,8 @@ gtk_gst_widget_init (GtkGstWidget * widget)
{
widget->priv = GTK_GST_WIDGET_GET_PRIVATE (widget);
+ widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+
g_mutex_init (&widget->priv->lock);
}