gtkglsink: Add rotate-method property
This mostly just takes code out of glimagesink and applies it here. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1088>
This commit is contained in:
parent
fdd7f9be23
commit
103ceb853a
@ -7114,7 +7114,20 @@
|
|||||||
"presence": "always"
|
"presence": "always"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {
|
||||||
|
"rotate-method": {
|
||||||
|
"blurb": "rotate method",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "identity (0)",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "GstVideoOrientationMethod",
|
||||||
|
"writable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"rank": "none"
|
"rank": "none"
|
||||||
},
|
},
|
||||||
"gtksink": {
|
"gtksink": {
|
||||||
|
@ -214,6 +214,24 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
|
|||||||
return gtk_sink->widget;
|
return gtk_sink->widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gst_gtk_base_sink_acquire_widget (GstGtkBaseSink * gtk_sink)
|
||||||
|
{
|
||||||
|
gpointer widget = NULL;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (gtk_sink);
|
||||||
|
if (gtk_sink->widget != NULL)
|
||||||
|
widget = gtk_sink->widget;
|
||||||
|
GST_OBJECT_UNLOCK (gtk_sink);
|
||||||
|
|
||||||
|
if (!widget)
|
||||||
|
widget =
|
||||||
|
gst_gtk_invoke_on_main ((GThreadFunc) gst_gtk_base_sink_get_widget,
|
||||||
|
gtk_sink);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
|
gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec)
|
GValue * value, GParamSpec * pspec)
|
||||||
@ -223,19 +241,7 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
|
|||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_WIDGET:
|
case PROP_WIDGET:
|
||||||
{
|
{
|
||||||
GObject *widget = NULL;
|
g_value_set_object (value, gst_gtk_base_sink_acquire_widget (gtk_sink));
|
||||||
|
|
||||||
GST_OBJECT_LOCK (gtk_sink);
|
|
||||||
if (gtk_sink->widget != NULL)
|
|
||||||
widget = G_OBJECT (gtk_sink->widget);
|
|
||||||
GST_OBJECT_UNLOCK (gtk_sink);
|
|
||||||
|
|
||||||
if (!widget)
|
|
||||||
widget =
|
|
||||||
gst_gtk_invoke_on_main ((GThreadFunc) gst_gtk_base_sink_get_widget,
|
|
||||||
gtk_sink);
|
|
||||||
|
|
||||||
g_value_set_object (value, widget);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PROP_FORCE_ASPECT_RATIO:
|
case PROP_FORCE_ASPECT_RATIO:
|
||||||
|
@ -91,6 +91,9 @@ struct _GstGtkBaseSinkClass
|
|||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstGtkBaseSink, gst_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstGtkBaseSink, gst_object_unref)
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gst_gtk_base_sink_acquire_widget (GstGtkBaseSink * gtk_sink);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_GTK_BASE_SINK_H__ */
|
#endif /* __GST_GTK_BASE_SINK_H__ */
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gl/gstglfuncs.h>
|
#include <gst/gl/gstglfuncs.h>
|
||||||
|
#include <gst/video/gstvideoaffinetransformationmeta.h>
|
||||||
|
|
||||||
#include "gstgtkglsink.h"
|
#include "gstgtkglsink.h"
|
||||||
#include "gtkgstglwidget.h"
|
#include "gtkgstglwidget.h"
|
||||||
@ -35,6 +36,11 @@
|
|||||||
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
|
||||||
|
|
||||||
|
static void gst_gtk_gl_sink_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_gtk_gl_sink_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
static gboolean gst_gtk_gl_sink_start (GstBaseSink * bsink);
|
static gboolean gst_gtk_gl_sink_start (GstBaseSink * bsink);
|
||||||
static gboolean gst_gtk_gl_sink_stop (GstBaseSink * bsink);
|
static gboolean gst_gtk_gl_sink_stop (GstBaseSink * bsink);
|
||||||
static gboolean gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query);
|
static gboolean gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query);
|
||||||
@ -42,6 +48,7 @@ static gboolean gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink,
|
|||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink,
|
static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
static gboolean gst_gtk_gl_sink_event (GstBaseSink * sink, GstEvent * event);
|
||||||
|
|
||||||
static void gst_gtk_gl_sink_finalize (GObject * object);
|
static void gst_gtk_gl_sink_finalize (GObject * object);
|
||||||
|
|
||||||
@ -63,6 +70,12 @@ GST_ELEMENT_REGISTER_DEFINE (gtkglsink, "gtkglsink", GST_RANK_NONE,
|
|||||||
GST_TYPE_GTK_GL_SINK);
|
GST_TYPE_GTK_GL_SINK);
|
||||||
|
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_ROTATE_METHOD,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
||||||
{
|
{
|
||||||
@ -76,6 +89,8 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
|||||||
gstbasesink_class = (GstBaseSinkClass *) klass;
|
gstbasesink_class = (GstBaseSinkClass *) klass;
|
||||||
gstgtkbasesink_class = (GstGtkBaseSinkClass *) klass;
|
gstgtkbasesink_class = (GstGtkBaseSinkClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->set_property = gst_gtk_gl_sink_set_property;
|
||||||
|
gobject_class->get_property = gst_gtk_gl_sink_get_property;
|
||||||
gobject_class->finalize = gst_gtk_gl_sink_finalize;
|
gobject_class->finalize = gst_gtk_gl_sink_finalize;
|
||||||
|
|
||||||
gstbasesink_class->query = gst_gtk_gl_sink_query;
|
gstbasesink_class->query = gst_gtk_gl_sink_query;
|
||||||
@ -83,10 +98,25 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
|||||||
gstbasesink_class->start = gst_gtk_gl_sink_start;
|
gstbasesink_class->start = gst_gtk_gl_sink_start;
|
||||||
gstbasesink_class->stop = gst_gtk_gl_sink_stop;
|
gstbasesink_class->stop = gst_gtk_gl_sink_stop;
|
||||||
gstbasesink_class->get_caps = gst_gtk_gl_sink_get_caps;
|
gstbasesink_class->get_caps = gst_gtk_gl_sink_get_caps;
|
||||||
|
gstbasesink_class->event = gst_gtk_gl_sink_event;
|
||||||
|
|
||||||
gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new;
|
gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new;
|
||||||
gstgtkbasesink_class->window_title = "Gtk+ GL renderer";
|
gstgtkbasesink_class->window_title = "Gtk+ GL renderer";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtkglsink:rotate-method:
|
||||||
|
*
|
||||||
|
* Rotation method #GstVideoOrientationMethod used to render the media
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ROTATE_METHOD,
|
||||||
|
g_param_spec_enum ("rotate-method",
|
||||||
|
"rotate method",
|
||||||
|
"rotate method",
|
||||||
|
GST_TYPE_VIDEO_ORIENTATION_METHOD, GST_VIDEO_ORIENTATION_IDENTITY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gst_element_class_set_metadata (gstelement_class, "Gtk GL Video Sink",
|
gst_element_class_set_metadata (gstelement_class, "Gtk GL Video Sink",
|
||||||
"Sink/Video", "A video sink that renders to a GtkWidget using OpenGL",
|
"Sink/Video", "A video sink that renders to a GtkWidget using OpenGL",
|
||||||
"Matthew Waters <matthew@centricular.com>");
|
"Matthew Waters <matthew@centricular.com>");
|
||||||
@ -100,6 +130,41 @@ 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) {
|
||||||
|
case PROP_ROTATE_METHOD:
|
||||||
|
gtk_gst_gl_widget_set_rotate_method (GTK_GST_GL_WIDGET
|
||||||
|
(gst_gtk_base_sink_acquire_widget (GST_GTK_BASE_SINK (object))),
|
||||||
|
g_value_get_enum (value), FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gtk_gl_sink_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_ROTATE_METHOD:
|
||||||
|
g_value_set_enum (value,
|
||||||
|
gtk_gst_gl_widget_get_rotate_method (GTK_GST_GL_WIDGET
|
||||||
|
(gst_gtk_base_sink_acquire_widget (GST_GTK_BASE_SINK (object)))));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
|
gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
|
||||||
{
|
{
|
||||||
@ -296,6 +361,8 @@ gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
|||||||
|
|
||||||
/* we also support various metadata */
|
/* we also support various metadata */
|
||||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
||||||
|
gst_query_add_allocation_meta (query,
|
||||||
|
GST_VIDEO_AFFINE_TRANSFORMATION_META_API_TYPE, 0);
|
||||||
|
|
||||||
if (gtk_sink->context->gl_vtable->FenceSync)
|
if (gtk_sink->context->gl_vtable->FenceSync)
|
||||||
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
|
gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, 0);
|
||||||
@ -365,3 +432,35 @@ gst_gtk_gl_sink_finalize (GObject * object)
|
|||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gtk_gl_sink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstTagList *taglist;
|
||||||
|
GstVideoOrientationMethod orientation;
|
||||||
|
gboolean ret;
|
||||||
|
GtkGstGLWidget *widget;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (sink, "handling %s event", GST_EVENT_TYPE_NAME (event));
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_TAG:
|
||||||
|
gst_event_parse_tag (event, &taglist);
|
||||||
|
|
||||||
|
if (gst_video_orientation_from_tag (taglist, &orientation)) {
|
||||||
|
|
||||||
|
widget = GTK_GST_GL_WIDGET
|
||||||
|
(gst_gtk_base_sink_acquire_widget (GST_GTK_BASE_SINK (sink)));
|
||||||
|
|
||||||
|
gtk_gst_gl_widget_set_rotate_method (widget, orientation, TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -66,6 +66,9 @@ struct _GtkGstGLWidgetPrivate
|
|||||||
GLint attr_texture;
|
GLint attr_texture;
|
||||||
GLuint current_tex;
|
GLuint current_tex;
|
||||||
GstGLOverlayCompositor *overlay_compositor;
|
GstGLOverlayCompositor *overlay_compositor;
|
||||||
|
GstVideoOrientationMethod rotate_method;
|
||||||
|
GstVideoOrientationMethod current_rotate_method;
|
||||||
|
const gfloat *transform_matrix;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GLfloat vertices[] = {
|
static const GLfloat vertices[] = {
|
||||||
@ -119,9 +122,18 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
|
|||||||
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||||
const GstGLFuncs *gl = priv->context->gl_vtable;
|
const GstGLFuncs *gl = priv->context->gl_vtable;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
GstGLSLStage *frag_stage, *vert_stage;
|
||||||
|
|
||||||
|
vert_stage = gst_glsl_stage_new_with_string (priv->context,
|
||||||
|
GL_VERTEX_SHADER, GST_GLSL_VERSION_NONE,
|
||||||
|
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
|
||||||
|
gst_gl_shader_string_vertex_mat4_vertex_transform);
|
||||||
|
frag_stage = gst_glsl_stage_new_default_fragment (priv->context);
|
||||||
|
|
||||||
gst_gl_insert_debug_marker (priv->other_context, "initializing redisplay");
|
gst_gl_insert_debug_marker (priv->other_context, "initializing redisplay");
|
||||||
if (!(priv->shader = gst_gl_shader_new_default (priv->context, &error))) {
|
if (!(priv->shader =
|
||||||
|
gst_gl_shader_new_link_with_stages (priv->context, &error, vert_stage,
|
||||||
|
frag_stage, NULL))) {
|
||||||
GST_ERROR ("Failed to initialize shader: %s", error->message);
|
GST_ERROR ("Failed to initialize shader: %s", error->message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,36 +166,107 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
|
|||||||
priv->initted = TRUE;
|
priv->initted = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rotate 90 */
|
||||||
|
static const gfloat clockwise_matrix[] = {
|
||||||
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* rotate 180 */
|
||||||
|
static const gfloat clockwise_180_matrix[] = {
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* rotate 270 */
|
||||||
|
static const gfloat counterclockwise_matrix[] = {
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* horizontal-flip */
|
||||||
|
static const gfloat horizontal_flip_matrix[] = {
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* vertical-flip */
|
||||||
|
static const gfloat vertical_flip_matrix[] = {
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* upper-left-diagonal */
|
||||||
|
static const gfloat upper_left_matrix[] = {
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* upper-right-diagonal */
|
||||||
|
static const gfloat upper_right_matrix[] = {
|
||||||
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
_redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
||||||
{
|
{
|
||||||
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||||
const GstGLFuncs *gl = priv->context->gl_vtable;
|
const GstGLFuncs *gl = priv->context->gl_vtable;
|
||||||
const GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
|
const GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||||
|
GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (gst_widget);
|
||||||
|
GtkWidget *widget = GTK_WIDGET (gst_widget);
|
||||||
|
|
||||||
|
|
||||||
if (gst_widget->base.force_aspect_ratio) {
|
if (gst_widget->base.force_aspect_ratio) {
|
||||||
GstVideoRectangle src, dst, result;
|
GstVideoRectangle src, dst, result;
|
||||||
gint widget_width, widget_height, widget_scale;
|
gint video_width, video_height, widget_scale;
|
||||||
|
|
||||||
gl->ClearColor (0.0, 0.0, 0.0, 0.0);
|
gl->ClearColor (0.0, 0.0, 0.0, 0.0);
|
||||||
gl->Clear (GL_COLOR_BUFFER_BIT);
|
gl->Clear (GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
widget_scale = gtk_widget_get_scale_factor ((GtkWidget *) gst_widget);
|
widget_scale = gtk_widget_get_scale_factor (widget);
|
||||||
widget_width = gtk_widget_get_allocated_width ((GtkWidget *) gst_widget);
|
|
||||||
widget_height = gtk_widget_get_allocated_height ((GtkWidget *) gst_widget);
|
if (priv->current_rotate_method == GST_VIDEO_ORIENTATION_90R
|
||||||
|
|| priv->current_rotate_method == GST_VIDEO_ORIENTATION_90L
|
||||||
|
|| priv->current_rotate_method == GST_VIDEO_ORIENTATION_UL_LR
|
||||||
|
|| priv->current_rotate_method == GST_VIDEO_ORIENTATION_UR_LL) {
|
||||||
|
video_width = base_widget->display_height;
|
||||||
|
video_height = base_widget->display_width;
|
||||||
|
} else {
|
||||||
|
video_width = base_widget->display_width;
|
||||||
|
video_height = base_widget->display_height;
|
||||||
|
}
|
||||||
|
|
||||||
src.x = 0;
|
src.x = 0;
|
||||||
src.y = 0;
|
src.y = 0;
|
||||||
src.w = gst_widget->base.display_width;
|
src.w = video_width;
|
||||||
src.h = gst_widget->base.display_height;
|
src.h = video_height;
|
||||||
|
|
||||||
dst.x = 0;
|
dst.x = 0;
|
||||||
dst.y = 0;
|
dst.y = 0;
|
||||||
dst.w = widget_width * widget_scale;
|
dst.w = gtk_widget_get_allocated_width (widget) * widget_scale;
|
||||||
dst.h = widget_height * widget_scale;
|
dst.h = gtk_widget_get_allocated_height (widget) * widget_scale;
|
||||||
|
|
||||||
gst_video_sink_center_rect (src, dst, &result, TRUE);
|
gst_video_sink_center_rect (src, dst, &result, TRUE);
|
||||||
|
|
||||||
|
GST_LOG ("Center src %dx%d into dst %dx%d result -> %dx%d",
|
||||||
|
src.w, src.h, dst.w, dst.h, result.w, result.h);
|
||||||
|
|
||||||
gl->Viewport (result.x, result.y, result.w, result.h);
|
gl->Viewport (result.x, result.y, result.w, result.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +280,26 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
|||||||
gl->BindTexture (GL_TEXTURE_2D, tex);
|
gl->BindTexture (GL_TEXTURE_2D, tex);
|
||||||
gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0);
|
gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
GstVideoAffineTransformationMeta *af_meta;
|
||||||
|
gfloat matrix[16];
|
||||||
|
|
||||||
|
af_meta =
|
||||||
|
gst_buffer_get_video_affine_transformation_meta (base_widget->buffer);
|
||||||
|
|
||||||
|
if (priv->transform_matrix) {
|
||||||
|
gfloat tmp[16];
|
||||||
|
|
||||||
|
gst_gl_get_affine_transformation_meta_as_ndc (af_meta, tmp);
|
||||||
|
gst_gl_multiply_matrix4 (tmp, priv->transform_matrix, matrix);
|
||||||
|
} else {
|
||||||
|
gst_gl_get_affine_transformation_meta_as_ndc (af_meta, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_gl_shader_set_uniform_matrix_4fv (priv->shader,
|
||||||
|
"u_transformation", 1, FALSE, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||||
|
|
||||||
if (gl->BindVertexArray)
|
if (gl->BindVertexArray)
|
||||||
@ -579,3 +682,78 @@ gtk_gst_gl_widget_get_display (GtkGstGLWidget * gst_widget)
|
|||||||
|
|
||||||
return gst_object_ref (gst_widget->priv->display);
|
return gst_object_ref (gst_widget->priv->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_gst_gl_widget_set_rotate_method (GtkGstGLWidget * gst_widget,
|
||||||
|
GstVideoOrientationMethod method, gboolean from_tag)
|
||||||
|
{
|
||||||
|
GstVideoOrientationMethod tag_method = GST_VIDEO_ORIENTATION_AUTO;
|
||||||
|
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||||
|
|
||||||
|
if (method == GST_VIDEO_ORIENTATION_CUSTOM) {
|
||||||
|
GST_WARNING_OBJECT (gst_widget, "unsupported custom orientation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GTK_GST_BASE_WIDGET_LOCK (gst_widget);
|
||||||
|
if (from_tag)
|
||||||
|
tag_method = method;
|
||||||
|
else
|
||||||
|
priv->rotate_method = method;
|
||||||
|
|
||||||
|
if (priv->rotate_method == GST_VIDEO_ORIENTATION_AUTO)
|
||||||
|
method = tag_method;
|
||||||
|
else
|
||||||
|
method = priv->rotate_method;
|
||||||
|
|
||||||
|
if (method != priv->current_rotate_method) {
|
||||||
|
GST_DEBUG ("Changing method from %d to %d",
|
||||||
|
priv->current_rotate_method, method);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case GST_VIDEO_ORIENTATION_IDENTITY:
|
||||||
|
priv->transform_matrix = NULL;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_90R:
|
||||||
|
priv->transform_matrix = clockwise_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_180:
|
||||||
|
priv->transform_matrix = clockwise_180_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_90L:
|
||||||
|
priv->transform_matrix = counterclockwise_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_HORIZ:
|
||||||
|
priv->transform_matrix = horizontal_flip_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_VERT:
|
||||||
|
priv->transform_matrix = vertical_flip_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_UL_LR:
|
||||||
|
priv->transform_matrix = upper_left_matrix;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_ORIENTATION_UR_LL:
|
||||||
|
priv->transform_matrix = upper_right_matrix;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->current_rotate_method = method;
|
||||||
|
}
|
||||||
|
GTK_GST_BASE_WIDGET_UNLOCK (gst_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstVideoOrientationMethod
|
||||||
|
gtk_gst_gl_widget_get_rotate_method (GtkGstGLWidget * gst_widget)
|
||||||
|
{
|
||||||
|
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||||
|
GstVideoOrientationMethod method;
|
||||||
|
|
||||||
|
GTK_GST_BASE_WIDGET_LOCK (gst_widget);
|
||||||
|
method = priv->current_rotate_method;
|
||||||
|
GTK_GST_BASE_WIDGET_UNLOCK (gst_widget);
|
||||||
|
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
@ -72,6 +72,12 @@ GstGLDisplay * gtk_gst_gl_widget_get_display (GtkGstGLWidget * widget)
|
|||||||
GstGLContext * gtk_gst_gl_widget_get_context (GtkGstGLWidget * widget);
|
GstGLContext * gtk_gst_gl_widget_get_context (GtkGstGLWidget * widget);
|
||||||
GstGLContext * gtk_gst_gl_widget_get_gtk_context (GtkGstGLWidget * widget);
|
GstGLContext * gtk_gst_gl_widget_get_gtk_context (GtkGstGLWidget * widget);
|
||||||
|
|
||||||
|
void gtk_gst_gl_widget_set_rotate_method (GtkGstGLWidget * gst_widget,
|
||||||
|
GstVideoOrientationMethod method, gboolean from_tag);
|
||||||
|
GstVideoOrientationMethod gtk_gst_gl_widget_get_rotate_method (
|
||||||
|
GtkGstGLWidget * gst_widget);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GTK_GST_GL_WIDGET_H__ */
|
#endif /* __GTK_GST_GL_WIDGET_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user