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