[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