mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 13:06:23 +00:00
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.
This commit is contained in:
parent
b9ebc71cc8
commit
a512a91598
6 changed files with 243 additions and 34 deletions
|
@ -32,6 +32,8 @@
|
||||||
GST_DEBUG_CATEGORY (gst_debug_gtk_gl_sink);
|
GST_DEBUG_CATEGORY (gst_debug_gtk_gl_sink);
|
||||||
#define GST_CAT_DEFAULT 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_finalize (GObject * object);
|
||||||
static void gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
|
static void gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * param_spec);
|
const GValue * value, GParamSpec * param_spec);
|
||||||
|
@ -62,8 +64,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
PROP_0,
|
||||||
PROP_WIDGET
|
PROP_WIDGET,
|
||||||
|
PROP_FORCE_ASPECT_RATIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -102,6 +105,13 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
||||||
"The GtkWidget to place in the widget heirachy",
|
"The GtkWidget to place in the widget heirachy",
|
||||||
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
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_element_class_add_pad_template (gstelement_class,
|
||||||
gst_static_pad_template_get (&gst_gtk_gl_sink_template));
|
gst_static_pad_template_get (&gst_gtk_gl_sink_template));
|
||||||
|
|
||||||
|
@ -120,17 +130,7 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_gtk_gl_sink_init (GstGtkGLSink * gtk_sink)
|
gst_gtk_gl_sink_init (GstGtkGLSink * gtk_sink)
|
||||||
{
|
{
|
||||||
}
|
gtk_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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->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
|
/* Take the floating ref, otherwise the destruction of the container will
|
||||||
* make this widget disapear possibly before we are done. */
|
* 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:
|
case PROP_WIDGET:
|
||||||
g_value_set_object (value, gst_gtk_gl_sink_get_widget (gtk_sink));
|
g_value_set_object (value, gst_gtk_gl_sink_get_widget (gtk_sink));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -65,6 +65,10 @@ struct _GstGtkGLSink
|
||||||
GstGLUpload *upload;
|
GstGLUpload *upload;
|
||||||
GstBuffer *uploaded_buffer;
|
GstBuffer *uploaded_buffer;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gboolean force_aspect_ratio;
|
||||||
|
GBinding *bind_aspect_ratio;
|
||||||
|
|
||||||
GstGtkGLSinkPrivate *priv;
|
GstGtkGLSinkPrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,13 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("BGRA"))
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("BGRA"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ARG_0,
|
PROP_0,
|
||||||
PROP_WIDGET
|
PROP_WIDGET,
|
||||||
|
PROP_FORCE_ASPECT_RATIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -100,6 +103,13 @@ gst_gtk_sink_class_init (GstGtkSinkClass * klass)
|
||||||
"The GtkWidget to place in the widget heirachy",
|
"The GtkWidget to place in the widget heirachy",
|
||||||
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
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_element_class_add_pad_template (gstelement_class,
|
||||||
gst_static_pad_template_get (&gst_gtk_sink_template));
|
gst_static_pad_template_get (&gst_gtk_sink_template));
|
||||||
|
|
||||||
|
@ -119,17 +129,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
|
static void
|
||||||
gst_gtk_sink_finalize (GObject * object)
|
gst_gtk_sink_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +153,9 @@ gst_gtk_sink_get_widget (GstGtkSink * gtk_sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_sink->widget = (GtkGstWidget *) gtk_gst_widget_new ();
|
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
|
/* Take the floating ref, other wise the destruction of the container will
|
||||||
* make this widget disapear possibly before we are done. */
|
* 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,
|
gst_gtk_sink_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec)
|
GValue * value, GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GstGtkSink *gtk_sink;
|
GstGtkSink *gtk_sink = GST_GTK_SINK (object);
|
||||||
|
|
||||||
gtk_sink = GST_GTK_SINK (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_WIDGET:
|
case PROP_WIDGET:
|
||||||
g_value_set_object (value, gst_gtk_sink_get_widget (gtk_sink));
|
g_value_set_object (value, gst_gtk_sink_get_widget (gtk_sink));
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -56,6 +56,10 @@ struct _GstGtkSink
|
||||||
|
|
||||||
GtkGstWidget *widget;
|
GtkGstWidget *widget;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gboolean force_aspect_ratio;
|
||||||
|
GBinding *bind_aspect_ratio;
|
||||||
|
|
||||||
GstGtkSinkPrivate *priv;
|
GstGtkSinkPrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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), \
|
#define GTK_GST_GL_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
||||||
GTK_TYPE_GST_GL_WIDGET, GtkGstGLWidgetPrivate))
|
GTK_TYPE_GST_GL_WIDGET, GtkGstGLWidgetPrivate))
|
||||||
|
|
||||||
|
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_FORCE_ASPECT_RATIO,
|
||||||
|
};
|
||||||
|
|
||||||
struct _GtkGstGLWidgetPrivate
|
struct _GtkGstGLWidgetPrivate
|
||||||
{
|
{
|
||||||
GMutex lock;
|
GMutex lock;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gboolean force_aspect_ratio;
|
||||||
|
|
||||||
gboolean negotiated;
|
gboolean negotiated;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstCaps *gl_caps;
|
GstCaps *gl_caps;
|
||||||
|
@ -182,6 +193,30 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
||||||
const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable;
|
const GstGLFuncs *gl = gst_widget->priv->context->gl_vtable;
|
||||||
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
|
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);
|
gst_gl_shader_use (gst_widget->priv->shader);
|
||||||
|
|
||||||
if (gl->BindVertexArray)
|
if (gl->BindVertexArray)
|
||||||
|
@ -390,19 +425,62 @@ gtk_gst_gl_widget_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (gtk_gst_gl_widget_parent_class)->finalize (object);
|
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
|
static void
|
||||||
gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass)
|
gtk_gst_gl_widget_class_init (GtkGstGLWidgetClass * klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *gobject_klass = (GObjectClass *) klass;
|
||||||
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
|
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
|
||||||
GtkGLAreaClass *gl_widget_klass = (GtkGLAreaClass *) klass;
|
GtkGLAreaClass *gl_widget_klass = (GtkGLAreaClass *) klass;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GtkGstGLWidgetPrivate));
|
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;
|
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_width = gtk_gst_gl_widget_get_preferred_width;
|
||||||
widget_klass->get_preferred_height = gtk_gst_gl_widget_get_preferred_height;
|
widget_klass->get_preferred_height = gtk_gst_gl_widget_get_preferred_height;
|
||||||
|
|
||||||
G_OBJECT_CLASS (klass)->finalize = gtk_gst_gl_widget_finalize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -412,6 +490,8 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * widget)
|
||||||
|
|
||||||
widget->priv = GTK_GST_GL_WIDGET_GET_PRIVATE (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);
|
g_mutex_init (&widget->priv->lock);
|
||||||
|
|
||||||
display = gdk_display_get_default ();
|
display = gdk_display_get_default ();
|
||||||
|
|
|
@ -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), \
|
#define GTK_GST_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
||||||
GTK_TYPE_GST_WIDGET, GtkGstWidgetPrivate))
|
GTK_TYPE_GST_WIDGET, GtkGstWidgetPrivate))
|
||||||
|
|
||||||
|
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_FORCE_ASPECT_RATIO,
|
||||||
|
};
|
||||||
|
|
||||||
struct _GtkGstWidgetPrivate
|
struct _GtkGstWidgetPrivate
|
||||||
{
|
{
|
||||||
GMutex lock;
|
GMutex lock;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
gboolean force_aspect_ratio;
|
||||||
|
|
||||||
gboolean negotiated;
|
gboolean negotiated;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstCaps *caps;
|
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) widget_width / GST_VIDEO_INFO_WIDTH (&frame.info);
|
||||||
gdouble scale_y =
|
gdouble scale_y =
|
||||||
(gdouble) widget_height / GST_VIDEO_INFO_HEIGHT (&frame.info);
|
(gdouble) widget_height / GST_VIDEO_INFO_HEIGHT (&frame.info);
|
||||||
|
GstVideoRectangle result;
|
||||||
|
|
||||||
gst_widget->priv->v_info = frame.info;
|
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,
|
CAIRO_FORMAT_ARGB32, frame.info.width, frame.info.height,
|
||||||
frame.info.stride[0]);
|
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_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_set_source_surface (cr, surface, 0, 0);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
@ -143,18 +179,60 @@ gtk_gst_widget_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (gtk_gst_widget_parent_class)->finalize (object);
|
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
|
static void
|
||||||
gtk_gst_widget_class_init (GtkGstWidgetClass * klass)
|
gtk_gst_widget_class_init (GtkGstWidgetClass * klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *gobject_klass = (GObjectClass *) klass;
|
||||||
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
|
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GtkGstWidgetPrivate));
|
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->draw = gtk_gst_widget_draw;
|
||||||
widget_klass->get_preferred_width = gtk_gst_widget_get_preferred_width;
|
widget_klass->get_preferred_width = gtk_gst_widget_get_preferred_width;
|
||||||
widget_klass->get_preferred_height = gtk_gst_widget_get_preferred_height;
|
widget_klass->get_preferred_height = gtk_gst_widget_get_preferred_height;
|
||||||
|
|
||||||
G_OBJECT_CLASS (klass)->finalize = gtk_gst_widget_finalize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -162,6 +240,8 @@ gtk_gst_widget_init (GtkGstWidget * widget)
|
||||||
{
|
{
|
||||||
widget->priv = GTK_GST_WIDGET_GET_PRIVATE (widget);
|
widget->priv = GTK_GST_WIDGET_GET_PRIVATE (widget);
|
||||||
|
|
||||||
|
widget->priv->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
||||||
|
|
||||||
g_mutex_init (&widget->priv->lock);
|
g_mutex_init (&widget->priv->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue