mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-04 22:48:54 +00:00
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
6 changed files with 328 additions and 23 deletions
|
@ -7114,7 +7114,20 @@
|
|||
"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"
|
||||
},
|
||||
"gtksink": {
|
||||
|
|
|
@ -214,6 +214,24 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
|
|||
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
|
||||
gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
|
@ -223,19 +241,7 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
|
|||
switch (prop_id) {
|
||||
case PROP_WIDGET:
|
||||
{
|
||||
GObject *widget = NULL;
|
||||
|
||||
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);
|
||||
g_value_set_object (value, gst_gtk_base_sink_acquire_widget (gtk_sink));
|
||||
break;
|
||||
}
|
||||
case PROP_FORCE_ASPECT_RATIO:
|
||||
|
|
|
@ -91,6 +91,9 @@ struct _GstGtkBaseSinkClass
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstGtkBaseSink, gst_object_unref)
|
||||
|
||||
GtkWidget *
|
||||
gst_gtk_base_sink_acquire_widget (GstGtkBaseSink * gtk_sink);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_GTK_BASE_SINK_H__ */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
#include <gst/video/gstvideoaffinetransformationmeta.h>
|
||||
|
||||
#include "gstgtkglsink.h"
|
||||
#include "gtkgstglwidget.h"
|
||||
|
@ -35,6 +36,11 @@
|
|||
GST_DEBUG_CATEGORY (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_stop (GstBaseSink * bsink);
|
||||
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);
|
||||
static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink,
|
||||
GstCaps * filter);
|
||||
static gboolean gst_gtk_gl_sink_event (GstBaseSink * sink, GstEvent * event);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ROTATE_METHOD,
|
||||
};
|
||||
|
||||
static void
|
||||
gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
||||
{
|
||||
|
@ -76,6 +89,8 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
|||
gstbasesink_class = (GstBaseSinkClass *) 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;
|
||||
|
||||
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->stop = gst_gtk_gl_sink_stop;
|
||||
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->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",
|
||||
"Sink/Video", "A video sink that renders to a GtkWidget using OpenGL",
|
||||
"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
|
||||
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 */
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
GLuint current_tex;
|
||||
GstGLOverlayCompositor *overlay_compositor;
|
||||
GstVideoOrientationMethod rotate_method;
|
||||
GstVideoOrientationMethod current_rotate_method;
|
||||
const gfloat *transform_matrix;
|
||||
};
|
||||
|
||||
static const GLfloat vertices[] = {
|
||||
|
@ -119,9 +122,18 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
|
|||
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||
const GstGLFuncs *gl = priv->context->gl_vtable;
|
||||
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");
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -154,36 +166,107 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
|
|||
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
|
||||
_redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
||||
{
|
||||
GtkGstGLWidgetPrivate *priv = gst_widget->priv;
|
||||
const GstGLFuncs *gl = priv->context->gl_vtable;
|
||||
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) {
|
||||
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->Clear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
widget_scale = gtk_widget_get_scale_factor ((GtkWidget *) gst_widget);
|
||||
widget_width = gtk_widget_get_allocated_width ((GtkWidget *) gst_widget);
|
||||
widget_height = gtk_widget_get_allocated_height ((GtkWidget *) gst_widget);
|
||||
widget_scale = gtk_widget_get_scale_factor (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.y = 0;
|
||||
src.w = gst_widget->base.display_width;
|
||||
src.h = gst_widget->base.display_height;
|
||||
src.w = video_width;
|
||||
src.h = video_height;
|
||||
|
||||
dst.x = 0;
|
||||
dst.y = 0;
|
||||
dst.w = widget_width * widget_scale;
|
||||
dst.h = widget_height * widget_scale;
|
||||
dst.w = gtk_widget_get_allocated_width (widget) * widget_scale;
|
||||
dst.h = gtk_widget_get_allocated_height (widget) * widget_scale;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -197,6 +280,26 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
|
|||
gl->BindTexture (GL_TEXTURE_2D, tex);
|
||||
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);
|
||||
|
||||
if (gl->BindVertexArray)
|
||||
|
@ -579,3 +682,78 @@ gtk_gst_gl_widget_get_display (GtkGstGLWidget * gst_widget)
|
|||
|
||||
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_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
|
||||
|
||||
#endif /* __GTK_GST_GL_WIDGET_H__ */
|
||||
|
|
Loading…
Reference in a new issue