From e876d9a5814be41a3f258214b0d24bb2b82707df Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 11 Jan 2013 11:12:26 +0100 Subject: [PATCH] overlay: fix check for pixels buffer change. A GstVideoOverlayRectangle is created whenever the underlying pixels data change. However, when global-alpha is supported, it is possible to re-use the same GstVideoOverlayRectangle but with a change to the global-alpha value. This process causes a change of sequence number, so we can no longer check for that. Still, if sequence numbers did not change, then there was no change in global-alpha either. So, we need a way to compare the underlying GstBuffer pointers. There is no API to retrieve the original pixels buffer from a GstVideoOverlayRectangle. So, we use the following heuristics: 1. Use gst_video_overlay_rectangle_get_pixels_unscaled_argb() with the same format flags from which the GstVideoOverlayRectangle was created. This will work if there was no prior consumer of the GstVideoOverlayRectangle with alternate (non-"native") format flags. 2. In overlay_rectangle_has_changed_pixels(), we have to use the same gst_video_overlay_rectangle_get_pixels_unscaled_argb() function but with flags that match the subpicture. This is needed to cope with platforms that don't support global-alpha in HW, so the gst-video layer takes care of that and fixes this up with a possibly new GstBuffer, and hence pixels data (or) in-place by caching the current global-alpha value applied. So we have to determine the rectangle was previously used, based on what previous flags were used to retrieve the ARGB pixels buffer. --- gst-libs/gst/vaapi/gstvaapicontext.c | 33 +++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c index db96dfb9e1..737c4aca1f 100644 --- a/gst-libs/gst/vaapi/gstvaapicontext.c +++ b/gst-libs/gst/vaapi/gstvaapicontext.c @@ -54,6 +54,7 @@ struct _GstVaapiOverlayRectangle { GstVaapiSubpicture *subpicture; GstVaapiRectangle render_rect; guint seq_num; + GstBuffer *rect_buffer; GstVideoOverlayRectangle *rect; guint is_associated : 1; }; @@ -104,6 +105,21 @@ gst_video_overlay_rectangle_replace(GstVideoOverlayRectangle **old_rect_ptr, GST_MINI_OBJECT_CAST(new_rect)); } +static inline GstBuffer * +gst_video_overlay_rectangle_get_pixels_raw(GstVideoOverlayRectangle *rect) +{ + guint width, height, stride, flags; + + flags = gst_video_overlay_rectangle_get_flags(rect); + + /* Try to retrieve the original buffer that was passed to + gst_video_overlay_rectangle_new_argb(). This will only work if + there was no previous user that required pixels with non native + alpha type */ + return gst_video_overlay_rectangle_get_pixels_unscaled_argb(rect, + &width, &height, &stride, flags); +} + #define overlay_rectangle_ref(overlay) \ gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay)) @@ -150,6 +166,11 @@ overlay_rectangle_new(GstVideoOverlayRectangle *rect, GstVaapiContext *context) overlay->seq_num = gst_video_overlay_rectangle_get_seqnum(rect); overlay->rect = gst_video_overlay_rectangle_ref(rect); + gst_buffer_replace(&overlay->rect_buffer, + gst_video_overlay_rectangle_get_pixels_raw(rect)); + if (!overlay->rect_buffer) + goto error; + overlay->subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle( GST_VAAPI_OBJECT_DISPLAY(context), rect); if (!overlay->subpicture) @@ -177,6 +198,7 @@ error: static void overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay) { + gst_buffer_replace(&overlay->rect_buffer, NULL); gst_video_overlay_rectangle_unref(overlay->rect); if (overlay->subpicture) { @@ -233,9 +255,18 @@ static gboolean overlay_rectangle_changed_pixels(GstVaapiOverlayRectangle *overlay, GstVideoOverlayRectangle *rect) { + guint width, height, stride, flags; + GstBuffer *buffer; + if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum(rect)) return FALSE; - return TRUE; + + flags = to_GstVideoOverlayFormatFlags( + gst_vaapi_subpicture_get_flags(overlay->subpicture)); + + buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb(rect, + &width, &height, &stride, flags); + return GST_BUFFER_DATA(overlay->rect_buffer) != GST_BUFFER_DATA(buffer); } static gboolean