basetextoverlay: Ensure meta coordinate are in stream scale
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Tue, 21 Jul 2015 22:40:59 +0000 (18:40 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 22 Jul 2015 17:24:04 +0000 (13:24 -0400)
The GstVideoOverlayComposition meta coordinates should always be
in stream scale, regardless of the window size downstream. This
way the sink can always scale the composition if the window size
have changed after a buffer (with his meta) was rendered before.

https://bugzilla.gnome.org/show_bug.cgi?id=751157

ext/pango/gstbasetextoverlay.c
ext/pango/gstbasetextoverlay.h

index cd7b2d3..c507fe9 100644 (file)
@@ -35,6 +35,7 @@
 #include "gstclockoverlay.h"
 #include "gsttextrender.h"
 #include <string.h>
+#include <math.h>
 
 /* FIXME:
  *  - use proper strides and offset for I420
@@ -641,12 +642,13 @@ gst_base_text_overlay_init (GstBaseTextOverlay * overlay,
   overlay->window_width = 1;
   overlay->window_height = 1;
 
-  overlay->stream_height = 1;
-  overlay->stream_width = 1;
-
   overlay->image_width = 1;
   overlay->image_height = 1;
 
+  overlay->render_width = 1;
+  overlay->render_height = 1;
+  overlay->render_scale = 1.0l;
+
   g_mutex_init (&overlay->lock);
   g_cond_init (&overlay->cond);
   gst_segment_init (&overlay->segment, GST_FORMAT_TIME);
@@ -747,8 +749,8 @@ gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps)
   }
 
   /* Initialize dimensions */
-  width = overlay->stream_width;
-  height = overlay->stream_height;
+  width = overlay->width;
+  height = overlay->height;
 
   if (upstream_has_meta) {
     overlay_caps = gst_caps_ref (caps);
@@ -793,17 +795,15 @@ gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps)
       if (gst_structure_get (params, "width", G_TYPE_UINT, &width,
               "height", G_TYPE_UINT, &height, NULL)) {
         GST_DEBUG ("received window size: %dx%d", width, height);
+        g_assert (width != 0 && height != 0);
       }
     }
   }
 
   /* Update render size if needed */
-  if ((width != 0 && height != 0) && (overlay->window_width != width
-          || overlay->window_height != height)) {
-    overlay->window_width = width;
-    overlay->window_height = height;
-    gst_base_text_overlay_update_render_size (overlay);
-  }
+  overlay->window_width = width;
+  overlay->window_height = height;
+  gst_base_text_overlay_update_render_size (overlay);
 
   gst_query_unref (query);
 
@@ -887,8 +887,8 @@ gst_base_text_overlay_setcaps (GstBaseTextOverlay * overlay, GstCaps * caps)
 
   overlay->info = info;
   overlay->format = GST_VIDEO_INFO_FORMAT (&info);
-  overlay->stream_width = GST_VIDEO_INFO_WIDTH (&info);
-  overlay->stream_height = GST_VIDEO_INFO_HEIGHT (&info);
+  overlay->width = GST_VIDEO_INFO_WIDTH (&info);
+  overlay->height = GST_VIDEO_INFO_HEIGHT (&info);
 
   ret = gst_base_text_overlay_negotiate (overlay, caps);
 
@@ -1154,11 +1154,9 @@ gst_base_text_overlay_src_query (GstPad * pad, GstObject * parent,
 static void
 gst_base_text_overlay_update_render_size (GstBaseTextOverlay * overlay)
 {
-  gfloat video_aspect = (float) overlay->stream_width /
-      (float) overlay->stream_height;
-
-  gfloat window_aspect = (float) overlay->window_width /
-      (float) overlay->window_height;
+  gdouble video_aspect = (gdouble) overlay->width / (gdouble) overlay->height;
+  gdouble window_aspect = (gdouble) overlay->window_width /
+      (gdouble) overlay->window_height;
 
   guint text_buffer_width = 0;
   guint text_buffer_height = 0;
@@ -1171,15 +1169,20 @@ gst_base_text_overlay_update_render_size (GstBaseTextOverlay * overlay)
     text_buffer_height = overlay->window_height;
   }
 
-  overlay->need_render = TRUE;
+  if ((overlay->render_width == text_buffer_width) &&
+      (overlay->render_height == text_buffer_height))
+    return;
 
-  overlay->width = text_buffer_width;
-  overlay->height = text_buffer_height;
-  GST_DEBUG
-      ("updating render dimensions %dx%d from stream %dx%d and window %dx%d",
-      overlay->width, overlay->height,
-      overlay->stream_width, overlay->stream_height,
-      overlay->window_width, overlay->window_height);
+  overlay->need_render = TRUE;
+  overlay->render_width = text_buffer_width;
+  overlay->render_height = text_buffer_height;
+  overlay->render_scale = (gdouble) overlay->render_width /
+      (gdouble) overlay->width;
+
+  GST_DEBUG ("updating render dimensions %dx%d from stream %dx%d, window %dx%d "
+      "and render scale %f", overlay->render_width, overlay->render_height,
+      overlay->width, overlay->height, overlay->window_width,
+      overlay->window_height, overlay->render_scale);
 }
 
 static gboolean
@@ -1430,8 +1433,8 @@ gst_base_text_overlay_get_pos (GstBaseTextOverlay * overlay,
   GstBaseTextOverlayVAlign valign;
   GstBaseTextOverlayHAlign halign;
 
-  width = overlay->image_width;
-  height = overlay->image_height;
+  width = overlay->image_width / overlay->render_scale;
+  height = overlay->image_height / overlay->render_scale;
 
   if (overlay->use_vertical_render)
     halign = GST_BASE_TEXT_OVERLAY_HALIGN_RIGHT;
@@ -1494,17 +1497,26 @@ gst_base_text_overlay_set_composition (GstBaseTextOverlay * overlay)
   gint xpos, ypos;
   GstVideoOverlayRectangle *rectangle;
 
-  gst_base_text_overlay_get_pos (overlay, &xpos, &ypos);
+  if (overlay->text_image && overlay->image_width != 1) {
+    gint render_width, render_height;
+
+    gst_base_text_overlay_get_pos (overlay, &xpos, &ypos);
+
+    render_width = round (overlay->image_width / overlay->render_scale);
+    render_height = round (overlay->image_height / overlay->render_scale);
 
-  GST_DEBUG ("updating composition for '%s' with window size %dx%d",
-      overlay->default_text, overlay->window_width, overlay->window_height);
+    GST_DEBUG ("updating composition for '%s' with window size %dx%d, "
+        "buffer size %dx%d, render size %dx%d and position (%d, %d)",
+        overlay->default_text, overlay->window_width, overlay->window_height,
+        overlay->image_width, overlay->image_height, render_width,
+        render_height, xpos, ypos);
 
-  if (overlay->text_image && overlay->image_width != 1) {
     gst_buffer_add_video_meta (overlay->text_image, GST_VIDEO_FRAME_FLAG_NONE,
         GST_VIDEO_OVERLAY_COMPOSITION_FORMAT_RGB,
         overlay->image_width, overlay->image_height);
+
     rectangle = gst_video_overlay_rectangle_new_raw (overlay->text_image,
-        xpos, ypos, overlay->image_width, overlay->image_height,
+        xpos, ypos, render_width, render_height,
         GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
 
     if (overlay->composition)
@@ -1564,6 +1576,7 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay,
     /* 640 pixel is default */
     scalef = (double) (overlay->width) / DEFAULT_SCALE_BASIS;
   }
+
   pango_layout_set_width (overlay->layout, -1);
   /* set text on pango layout */
   pango_layout_set_markup (overlay->layout, string, textlen);
@@ -1571,7 +1584,7 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay,
   /* get subtitle image size */
   pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect);
 
-  width = (logical_rect.width + overlay->shadow_offset) * scalef;
+  width = ceil ((logical_rect.width + overlay->shadow_offset) * scalef);
 
   if (width + overlay->deltax >
       (overlay->use_vertical_render ? overlay->height : overlay->width)) {
@@ -1584,11 +1597,17 @@ gst_base_text_overlay_render_pangocairo (GstBaseTextOverlay * overlay,
     width = overlay->width;
   }
 
-  height =
-      (logical_rect.height + logical_rect.y + overlay->shadow_offset) * scalef;
+  height = ceil (
+      (logical_rect.height + logical_rect.y + overlay->shadow_offset) * scalef);
   if (height > overlay->height) {
     height = overlay->height;
   }
+
+  /* scale to reported window size */
+  width = ceil (width * overlay->render_scale);
+  height = ceil (height * overlay->render_scale);
+  scalef *= overlay->render_scale;
+
   if (overlay->use_vertical_render) {
     PangoRectangle rect;
     PangoContext *context;
index ef06394..1fb6d99 100644 (file)
@@ -143,8 +143,8 @@ struct _GstBaseTextOverlay {
     /* stream metrics */
     GstVideoInfo             info;
     GstVideoFormat           format;
-    gint                     stream_width;
-    gint                     stream_height;
+    gint                     width;
+    gint                     height;
 
     /* properties */
     gint                     xpad;
@@ -176,17 +176,19 @@ struct _GstBaseTextOverlay {
     gboolean                 need_render;
     GstBuffer               *text_image;
 
-    /* rendering canvas dimension, this is adjusted to compensate the
-     * downstream reported window size. */
-    gint                     width;
-    gint                     height;
+    /* dimension relative to witch the render is done, this is the stream size
+     * or a portion of the window_size (adapted to aspect ratio) */
+    gint                     render_width;
+    gint                     render_height;
+    /* This is (render_width / width) uses to convert to stream scale */
+    gdouble                  render_scale;
 
     /* dimension of text_image, the physical dimension */
     gint                     image_width;
     gint                     image_height;
 
     /* window dimension, reported in the composition meta params. This is set
-     * to stream_width, stream_height if missing */
+     * to stream width, height if missing */
     gint                     window_width;
     gint                     window_height;