[OE-core] [poky][PATCH 1/4] gstreamer1.0-plugins-bad: Support video rotation by using transform matrix
Yuqing Zhu
carol.zhu at nxp.com
Tue Oct 11 10:49:09 UTC 2016
Add "rotate-method" to glimagesink and apply transform matrix
to vertex coordinate to control rotation.
Signed-off-by: Yuqing Zhu <carol.zhu at nxp.com>
---
...-glplugin-glimagesink-support-video-rotat.patch | 574 +++++++++++++++++++++
.../gstreamer/gstreamer1.0-plugins-bad_1.8.3.bb | 1 +
2 files changed, 575 insertions(+)
create mode 100755 meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-glplugin-glimagesink-support-video-rotat.patch
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-glplugin-glimagesink-support-video-rotat.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-glplugin-glimagesink-support-video-rotat.patch
new file mode 100755
index 0000000..b00782c
--- /dev/null
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0010-glplugin-glimagesink-support-video-rotat.patch
@@ -0,0 +1,574 @@
+From 31c18b0796b433c5a3cfda90960dd394b16f8f1e Mon Sep 17 00:00:00 2001
+From: Haihua Hu <jared.hu at nxp.com>
+Date: Mon, 9 May 2016 20:26:51 +0800
+Subject: [PATCH] [MMFMWK-7151] [glplugin] glimagesink: support video rotation
+ using transform matrix
+
+Add "rotate-method" to glimagesink and apply transform matrix
+to vertex coordinate to control rotation.
+
+Upstream-Status: Backport[1.9.1]
+
+https://bugzilla.gnome.org/show_bug.cgi?id=765795
+
+Signed-off-by: Haihua Hu <jared.hu at nxp.com>
+---
+ ext/gl/gstglimagesink.c | 266 ++++++++++++++++++++++++++++++++---
+ ext/gl/gstglimagesink.h | 18 +++
+ gst-libs/gst/gl/gstglshaderstrings.c | 11 ++
+ gst-libs/gst/gl/gstglshaderstrings.h | 1 +
+ gst-libs/gst/gl/gstglutils.c | 60 ++++++++
+ gst-libs/gst/gl/gstglutils.h | 5 +
+ 6 files changed, 344 insertions(+), 17 deletions(-)
+
+diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c
+index 185577f..fb60468 100644
+--- a/ext/gl/gstglimagesink.c
++++ b/ext/gl/gstglimagesink.c
+@@ -120,6 +120,7 @@ G_DEFINE_TYPE (GstGLImageSinkBin, gst_gl_image_sink_bin, GST_TYPE_GL_SINK_BIN);
+ enum
+ {
+ PROP_BIN_0,
++ PROP_BIN_ROTATE_METHOD,
+ PROP_BIN_FORCE_ASPECT_RATIO,
+ PROP_BIN_PIXEL_ASPECT_RATIO,
+ PROP_BIN_HANDLE_EVENTS,
+@@ -181,6 +182,39 @@ _on_client_draw (GstGLImageSink * sink, GstGLContext * context,
+ return ret;
+ }
+
++#define DEFAULT_ROTATE_METHOD GST_GL_ROTATE_METHOD_IDENTITY
++
++#define GST_TYPE_GL_ROTATE_METHOD (gst_gl_rotate_method_get_type())
++
++static const GEnumValue rotate_methods[] = {
++ {GST_GL_ROTATE_METHOD_IDENTITY, "Identity (no rotation)", "none"},
++ {GST_GL_ROTATE_METHOD_90R, "Rotate clockwise 90 degrees", "clockwise"},
++ {GST_GL_ROTATE_METHOD_180, "Rotate 180 degrees", "rotate-180"},
++ {GST_GL_ROTATE_METHOD_90L, "Rotate counter-clockwise 90 degrees",
++ "counterclockwise"},
++ {GST_GL_ROTATE_METHOD_FLIP_HORIZ, "Flip horizontally", "horizontal-flip"},
++ {GST_GL_ROTATE_METHOD_FLIP_VERT, "Flip vertically", "vertical-flip"},
++ {GST_GL_ROTATE_METHOD_FLIP_UL_LR,
++ "Flip across upper left/lower right diagonal", "upper-left-diagonal"},
++ {GST_GL_ROTATE_METHOD_FLIP_UR_LL,
++ "Flip across upper right/lower left diagonal", "upper-right-diagonal"},
++ {GST_GL_ROTATE_METHOD_AUTO,
++ "Select rotate method based on image-orientation tag", "automatic"},
++ {0, NULL, NULL},
++};
++
++static GType
++gst_gl_rotate_method_get_type (void)
++{
++ static GType rotate_method_type = 0;
++
++ if (!rotate_method_type) {
++ rotate_method_type = g_enum_register_static ("GstGLRotateMethod",
++ rotate_methods);
++ }
++ return rotate_method_type;
++}
++
+ static void
+ gst_gl_image_sink_bin_init (GstGLImageSinkBin * self)
+ {
+@@ -203,6 +237,12 @@ gst_gl_image_sink_bin_class_init (GstGLImageSinkBinClass * klass)
+ gobject_class->set_property = gst_gl_image_sink_bin_set_property;
+
+ /* gl sink */
++ g_object_class_install_property (gobject_class, PROP_BIN_ROTATE_METHOD,
++ g_param_spec_enum ("rotate-method",
++ "rotate method",
++ "rotate method",
++ GST_TYPE_GL_ROTATE_METHOD, DEFAULT_ROTATE_METHOD,
++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BIN_FORCE_ASPECT_RATIO,
+ g_param_spec_boolean ("force-aspect-ratio",
+ "Force aspect ratio",
+@@ -291,6 +331,7 @@ static void gst_glimage_sink_set_property (GObject * object, guint prop_id,
+ static void gst_glimage_sink_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * param_spec);
+
++static gboolean gst_glimage_sink_event (GstBaseSink *sink, GstEvent * event);
+ static gboolean gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query);
+ static void gst_glimage_sink_set_context (GstElement * element,
+ GstContext * context);
+@@ -347,6 +388,7 @@ enum
+ {
+ ARG_0,
+ ARG_DISPLAY,
++ PROP_ROTATE_METHOD,
+ PROP_FORCE_ASPECT_RATIO,
+ PROP_PIXEL_ASPECT_RATIO,
+ PROP_CONTEXT,
+@@ -404,6 +446,128 @@ _display_size_to_stream_size (GstGLImageSink * gl_sink, gdouble x,
+ GST_TRACE ("transform %fx%f into %fx%f", x, y, *stream_x, *stream_y);
+ }
+
++/* rotate 90 */
++static const gfloat clockwise_matrix[] = {
++ 0.0f, -1.0f, 0.0, 0.0f,
++ 1.0f, 0.0f, 0.0, 0.0f,
++ 0.0f, 0.0f, 1.0, 0.0f,
++ 0.0f, 0.0f, 0.0, 1.0f,
++};
++
++/* rotate 180 */
++static const gfloat clockwise_180_matrix[] = {
++ -1.0f, 0.0f, 0.0, 0.0f,
++ 0.0f, -1.0f, 0.0, 0.0f,
++ 0.0f, 0.0f, 1.0, 0.0f,
++ 0.0f, 0.0f, 0.0, 1.0f,
++};
++
++/* rotate 270 */
++static const gfloat counterclockwise_matrix[] = {
++ 0.0f, 1.0f, 0.0, 0.0f,
++ -1.0f, 0.0f, 0.0, 0.0f,
++ 0.0f, 0.0f, 1.0, 0.0f,
++ 0.0f, 0.0f, 0.0, 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
++gst_glimage_sink_set_rotate_method(GstGLImageSink *gl_sink,
++ GstGLRotateMethod method, gboolean from_tag)
++{
++ GstGLRotateMethod tag_method;
++ GST_GLIMAGE_SINK_LOCK (gl_sink);
++ if (from_tag)
++ tag_method = method;
++ else
++ gl_sink->rotate_method = method;
++
++ if (gl_sink->rotate_method == GST_GL_ROTATE_METHOD_AUTO)
++ method = tag_method;
++ else
++ method = gl_sink->rotate_method;
++
++ if (method != gl_sink->current_rotate_method)
++ {
++ GST_DEBUG_OBJECT (gl_sink, "Changing method from %s to %s",
++ rotate_methods[gl_sink->current_rotate_method].value_nick,
++ rotate_methods[method].value_nick);
++
++ switch (method)
++ {
++ case GST_GL_ROTATE_METHOD_IDENTITY:
++ gl_sink->transform_matrix = NULL;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_90R:
++ gl_sink->transform_matrix = clockwise_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_180:
++ gl_sink->transform_matrix = clockwise_180_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_90L:
++ gl_sink->transform_matrix = counterclockwise_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_FLIP_HORIZ:
++ gl_sink->transform_matrix = horizontal_flip_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_FLIP_VERT:
++ gl_sink->transform_matrix = vertical_flip_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_FLIP_UL_LR:
++ gl_sink->transform_matrix = upper_left_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ case GST_GL_ROTATE_METHOD_FLIP_UR_LL:
++ gl_sink->transform_matrix = upper_right_matrix;
++ gl_sink->output_mode_changed = TRUE;
++ break;
++ default:
++ g_assert_not_reached();
++ break;
++ }
++
++ gl_sink->current_rotate_method = method;
++ }
++ GST_GLIMAGE_SINK_UNLOCK (gl_sink);
++}
++
+ static void
+ gst_glimage_sink_navigation_send_event (GstNavigation * navigation, GstStructure
+ * structure)
+@@ -485,6 +649,13 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass)
+ gobject_class->set_property = gst_glimage_sink_set_property;
+ gobject_class->get_property = gst_glimage_sink_get_property;
+
++ g_object_class_install_property (gobject_class, PROP_ROTATE_METHOD,
++ g_param_spec_enum ("rotate-method",
++ "rotate method",
++ "rotate method",
++ GST_TYPE_GL_ROTATE_METHOD, DEFAULT_ROTATE_METHOD,
++ G_PARAM_READWRITE | 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",
+@@ -577,6 +748,7 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass)
+
+ gstelement_class->change_state = gst_glimage_sink_change_state;
+ gstelement_class->set_context = gst_glimage_sink_set_context;
++ gstbasesink_class->event = gst_glimage_sink_event;
+ gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_glimage_sink_query);
+ gstbasesink_class->set_caps = gst_glimage_sink_set_caps;
+ gstbasesink_class->get_caps = gst_glimage_sink_get_caps;
+@@ -610,6 +782,9 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink)
+ glimage_sink->mview_output_flags = DEFAULT_MULTIVIEW_FLAGS;
+ glimage_sink->mview_downmix_mode = DEFAULT_MULTIVIEW_DOWNMIX;
+
++ glimage_sink->current_rotate_method = DEFAULT_ROTATE_METHOD;
++ glimage_sink->transform_matrix = NULL;
++
+ g_mutex_init (&glimage_sink->drawing_lock);
+ }
+
+@@ -624,6 +799,9 @@ gst_glimage_sink_set_property (GObject * object, guint prop_id,
+ glimage_sink = GST_GLIMAGE_SINK (object);
+
+ switch (prop_id) {
++ case PROP_ROTATE_METHOD:
++ gst_glimage_sink_set_rotate_method (glimage_sink, g_value_get_enum (value), FALSE);
++ break;
+ case PROP_FORCE_ASPECT_RATIO:
+ {
+ glimage_sink->keep_aspect_ratio = g_value_get_boolean (value);
+@@ -691,6 +869,9 @@ gst_glimage_sink_get_property (GObject * object, guint prop_id,
+ glimage_sink = GST_GLIMAGE_SINK (object);
+
+ switch (prop_id) {
++ case PROP_ROTATE_METHOD:
++ g_value_set_enum (value, glimage_sink->current_rotate_method);
++ break;
+ case PROP_FORCE_ASPECT_RATIO:
+ g_value_set_boolean (value, glimage_sink->keep_aspect_ratio);
+ break;
+@@ -848,6 +1029,50 @@ context_error:
+ }
+
+ static gboolean
++gst_glimage_sink_event (GstBaseSink *sink, GstEvent * event)
++{
++ GstGLImageSink *gl_sink = GST_GLIMAGE_SINK (sink);
++ GstTagList *taglist;
++ gchar *orientation;
++ gboolean ret;
++
++ GST_DEBUG_OBJECT (gl_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_tag_list_get_string (taglist, "image-orientation", &orientation)) {
++ if (!g_strcmp0 ("rotate-0", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_IDENTITY, TRUE);
++ else if (!g_strcmp0 ("rotate-90", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_90R, TRUE);
++ else if (!g_strcmp0 ("rotate-180", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_180, TRUE);
++ else if (!g_strcmp0 ("rotate-270", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_90L, TRUE);
++ else if (!g_strcmp0 ("flip-rotate-0", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_FLIP_HORIZ, TRUE);
++ else if (!g_strcmp0 ("flip-rotate-90", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_FLIP_UR_LL, TRUE);
++ else if (!g_strcmp0 ("flip-rotate-180", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_FLIP_VERT, TRUE);
++ else if (!g_strcmp0 ("flip-rotate-270", orientation))
++ gst_glimage_sink_set_rotate_method (gl_sink, GST_GL_ROTATE_METHOD_FLIP_UL_LR, TRUE);
++
++ g_free (orientation);
++ }
++ break;
++ default:
++ break;
++ }
++
++ ret = GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
++
++ return ret;
++}
++
++static gboolean
+ gst_glimage_sink_query (GstBaseSink * bsink, GstQuery * query)
+ {
+ GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (bsink);
+@@ -1817,7 +2042,10 @@ gst_glimage_sink_thread_init_redisplay (GstGLImageSink * gl_sink)
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ gst_gl_shader_string_fragment_external_oes_default);
+ } else {
+- vert_stage = gst_glsl_stage_new_default_vertex (gl_sink->context);
++ vert_stage = gst_glsl_stage_new_with_string (gl_sink->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 (gl_sink->context);
+ }
+ if (!vert_stage || !frag_stage) {
+@@ -1943,8 +2171,16 @@ gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height)
+
+ src.x = 0;
+ src.y = 0;
+- src.w = GST_VIDEO_SINK_WIDTH (gl_sink);
+- src.h = GST_VIDEO_SINK_HEIGHT (gl_sink);
++ if (gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_90R
++ || gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_90L
++ || gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_FLIP_UL_LR
++ || gl_sink->current_rotate_method == GST_GL_ROTATE_METHOD_FLIP_UR_LL) {
++ src.h = GST_VIDEO_SINK_WIDTH (gl_sink);
++ src.w = GST_VIDEO_SINK_HEIGHT (gl_sink);
++ } else {
++ src.w = GST_VIDEO_SINK_WIDTH (gl_sink);
++ src.h = GST_VIDEO_SINK_HEIGHT (gl_sink);
++ }
+
+ dst.x = 0;
+ dst.y = 0;
+@@ -1974,13 +2210,6 @@ gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height)
+ GST_GLIMAGE_SINK_UNLOCK (gl_sink);
+ }
+
+-static const gfloat identity_matrix[] = {
+- 1.0f, 0.0f, 0.0, 0.0f,
+- 0.0f, 1.0f, 0.0, 0.0f,
+- 0.0f, 0.0f, 1.0, 0.0f,
+- 0.0f, 0.0f, 0.0, 1.0f,
+-};
+-
+ static void
+ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
+ {
+@@ -2109,18 +2338,21 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
+ gl->ActiveTexture (GL_TEXTURE0);
+ gl->BindTexture (gl_target, gl_sink->redisplay_texture);
+ gst_gl_shader_set_uniform_1i (gl_sink->redisplay_shader, "tex", 0);
+- if (gl_sink->texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
++ {
+ GstVideoAffineTransformationMeta *af_meta;
++ gfloat matrix[16];
+
+ af_meta =
+ gst_buffer_get_video_affine_transformation_meta
+ (gl_sink->stored_buffer[0]);
+- if (af_meta)
+- gst_gl_shader_set_uniform_matrix_4fv (gl_sink->redisplay_shader,
+- "u_transformation", 1, FALSE, af_meta->matrix);
+- else
+- gst_gl_shader_set_uniform_matrix_4fv (gl_sink->redisplay_shader,
+- "u_transformation", 1, FALSE, identity_matrix);
++
++ gst_gl_get_affine_transformation_meta_as_ndc (af_meta, matrix);
++
++ if (gl_sink->transform_matrix)
++ gst_gl_multiply_matrix4 (gl_sink->transform_matrix, matrix, matrix);
++
++ gst_gl_shader_set_uniform_matrix_4fv (gl_sink->redisplay_shader,
++ "u_transformation", 1, FALSE, matrix);
+ }
+
+ gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
+diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h
+index f9a052a..cb0f4a6 100644
+--- a/ext/gl/gstglimagesink.h
++++ b/ext/gl/gstglimagesink.h
+@@ -44,6 +44,19 @@ GST_DEBUG_CATEGORY_EXTERN (gst_debug_glimage_sink);
+ #define GST_IS_GLIMAGE_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GLIMAGE_SINK))
+
++typedef enum
++{
++ GST_GL_ROTATE_METHOD_IDENTITY,
++ GST_GL_ROTATE_METHOD_90R,
++ GST_GL_ROTATE_METHOD_180,
++ GST_GL_ROTATE_METHOD_90L,
++ GST_GL_ROTATE_METHOD_FLIP_HORIZ,
++ GST_GL_ROTATE_METHOD_FLIP_VERT,
++ GST_GL_ROTATE_METHOD_FLIP_UL_LR,
++ GST_GL_ROTATE_METHOD_FLIP_UR_LL,
++ GST_GL_ROTATE_METHOD_AUTO
++}GstGLRotateMethod;
++
+ typedef struct _GstGLImageSink GstGLImageSink;
+ typedef struct _GstGLImageSinkClass GstGLImageSinkClass;
+
+@@ -102,6 +115,11 @@ struct _GstGLImageSink
+ GstGLSyncMeta *stored_sync_meta;
+ GLuint redisplay_texture;
+
++ /* current video flip method */
++ GstGLRotateMethod current_rotate_method;
++ GstGLRotateMethod rotate_method;
++ const gfloat *transform_matrix;
++
+ /* protected with drawing_lock */
+ gboolean window_resized;
+ guint window_width;
+diff --git a/gst-libs/gst/gl/gstglshaderstrings.c b/gst-libs/gst/gl/gstglshaderstrings.c
+index 729be6f..10186f1 100644
+--- a/gst-libs/gst/gl/gstglshaderstrings.c
++++ b/gst-libs/gst/gl/gstglshaderstrings.c
+@@ -35,6 +35,17 @@ const gchar *gst_gl_shader_string_vertex_default =
+ " v_texcoord = a_texcoord;\n"
+ "}\n";
+
++const gchar *gst_gl_shader_string_vertex_mat4_vertex_transform =
++ "uniform mat4 u_transformation;\n"
++ "attribute vec4 a_position;\n"
++ "attribute vec2 a_texcoord;\n"
++ "varying vec2 v_texcoord;\n"
++ "void main()\n"
++ "{\n"
++ " gl_Position = u_transformation * a_position;\n"
++ " v_texcoord = a_texcoord;\n"
++ "}\n";
++
+ const gchar *gst_gl_shader_string_vertex_mat4_texture_transform =
+ "uniform mat4 u_transformation;\n"
+ "attribute vec4 a_position;\n"
+diff --git a/gst-libs/gst/gl/gstglshaderstrings.h b/gst-libs/gst/gl/gstglshaderstrings.h
+index 49ea8de..f9a13c8 100644
+--- a/gst-libs/gst/gl/gstglshaderstrings.h
++++ b/gst-libs/gst/gl/gstglshaderstrings.h
+@@ -28,6 +28,7 @@ G_BEGIN_DECLS
+ extern const gchar *gst_gl_shader_string_vertex_default;
+ extern const gchar *gst_gl_shader_string_fragment_default;
+
++extern const gchar *gst_gl_shader_string_vertex_mat4_vertex_transform;
+ extern const gchar *gst_gl_shader_string_vertex_mat4_texture_transform;
+ extern const gchar *gst_gl_shader_string_fragment_external_oes_default;
+
+diff --git a/gst-libs/gst/gl/gstglutils.c b/gst-libs/gst/gl/gstglutils.c
+index e2e04e4..a38772f 100644
+--- a/gst-libs/gst/gl/gstglutils.c
++++ b/gst-libs/gst/gl/gstglutils.c
+@@ -1067,3 +1067,63 @@ gst_gl_value_set_texture_target_from_mask (GValue * value,
+ return ret;
+ }
+ }
++
++static const gfloat identity_matrix[] = {
++ 1.0f, 0.0f, 0.0, 0.0f,
++ 0.0f, 1.0f, 0.0, 0.0f,
++ 0.0f, 0.0f, 1.0, 0.0f,
++ 0.0f, 0.0f, 0.0, 1.0f,
++};
++
++static const gfloat from_ndc_matrix[] = {
++ 0.5f, 0.0f, 0.0, 0.5f,
++ 0.0f, 0.5f, 0.0, 0.5f,
++ 0.0f, 0.0f, 0.5, 0.5f,
++ 0.0f, 0.0f, 0.0, 1.0f,
++};
++
++static const gfloat to_ndc_matrix[] = {
++ 2.0f, 0.0f, 0.0, -1.0f,
++ 0.0f, 2.0f, 0.0, -1.0f,
++ 0.0f, 0.0f, 2.0, -1.0f,
++ 0.0f, 0.0f, 0.0, 1.0f,
++};
++
++void
++gst_gl_multiply_matrix4 (const gfloat * a, const gfloat * b, gfloat * result)
++{
++ int i, j, k;
++ gfloat tmp[16] = { 0.0f };
++
++ if (!a || !b || !result)
++ return;
++
++ for (i = 0; i < 4; i++) {
++ for (j = 0; j < 4; j++) {
++ for (k = 0; k < 4; k++) {
++ tmp[i + (j * 4)] += a[i + (k * 4)] * b[k + (j * 4)];
++ }
++ }
++ }
++
++ for (i = 0; i < 16; i++)
++ result[i] = tmp[i];
++}
++
++void
++gst_gl_get_affine_transformation_meta_as_ndc (GstVideoAffineTransformationMeta *
++ meta, gfloat * matrix)
++{
++ if (!meta) {
++ int i;
++
++ for (i = 0; i < 16; i++) {
++ matrix[i] = identity_matrix[i];
++ }
++ } else {
++ gfloat tmp[16] = { 0.0f };
++
++ gst_gl_multiply_matrix4 (from_ndc_matrix, meta->matrix, tmp);
++ gst_gl_multiply_matrix4 (tmp, to_ndc_matrix, matrix);
++ }
++}
+diff --git a/gst-libs/gst/gl/gstglutils.h b/gst-libs/gst/gl/gstglutils.h
+index 1c5ab12..fc12801 100644
+--- a/gst-libs/gst/gl/gstglutils.h
++++ b/gst-libs/gst/gl/gstglutils.h
+@@ -24,6 +24,7 @@
+ #include <gst/video/video.h>
+
+ #include <gst/gl/gstgl_fwd.h>
++#include <gst/video/gstvideoaffinetransformationmeta.h>
+
+ G_BEGIN_DECLS
+
+@@ -116,6 +117,10 @@ gboolean gst_gl_value_set_texture_target_from_mask (GValue * value,
+ gboolean gst_gl_value_set_texture_target (GValue * value, GstGLTextureTarget target);
+ GstGLTextureTarget gst_gl_value_get_texture_target_mask (const GValue * value);
+
++void gst_gl_multiply_matrix4 (const gfloat * a, const gfloat * b, gfloat * result);
++void gst_gl_get_affine_transformation_meta_as_ndc (GstVideoAffineTransformationMeta *
++ meta, gfloat * matrix);
++
+ G_END_DECLS
+
+ #endif /* __GST_GL_UTILS_H__ */
+--
+1.9.1
+
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.8.3.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.8.3.bb
index 108f4db..358c5d1 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.8.3.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.8.3.bb
@@ -19,6 +19,7 @@ SRC_URI = " \
file://0006-glcolorconvert-GLES3-deprecates-texture2D-and-it-doe.patch \
file://0008-gl-implement-GstGLMemoryEGL.patch \
file://0009-glimagesink-Downrank-to-marginal.patch \
+ file://0010-glplugin-glimagesink-support-video-rotat.patch \
"
SRC_URI[md5sum] = "955281a43e98c5464563fa049e0a0911"
SRC_URI[sha256sum] = "7899fcb18e6a1af2888b19c90213af018a57d741c6e72ec56b133bc73ec8509b"
--
1.9.1
More information about the Openembedded-core
mailing list