For both the software and the GL sink's.
Doesn't deal with the pixel-aspect-ratio field at all yet.
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);
enum
{
- ARG_0,
- PROP_WIDGET
+ PROP_0,
+ PROP_WIDGET,
+ PROP_FORCE_ASPECT_RATIO,
};
enum
"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));
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
}
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. */
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;
GstGLUpload *upload;
GstBuffer *uploaded_buffer;
+ /* properties */
+ gboolean force_aspect_ratio;
+ GBinding *bind_aspect_ratio;
+
GstGtkGLSinkPrivate *priv;
};
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
"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));
{
}
-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)
{
}
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. */
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;
GtkGstWidget *widget;
+ /* properties */
+ gboolean force_aspect_ratio;
+ GBinding *bind_aspect_ratio;
+
GstGtkSinkPrivate *priv;
};
#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;
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)
G_OBJECT_CLASS (gtk_gst_gl_widget_parent_class)->finalize (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
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 ();
#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;
(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;
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);
G_OBJECT_CLASS (gtk_gst_widget_parent_class)->finalize (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
{
widget->priv = GTK_GST_WIDGET_GET_PRIVATE (widget);
+ widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
+
g_mutex_init (&widget->priv->lock);
}