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.
This commit is contained in:
Gwenole Beauchesne 2013-01-11 11:12:26 +01:00
parent a14d259060
commit e876d9a581

View file

@ -54,6 +54,7 @@ struct _GstVaapiOverlayRectangle {
GstVaapiSubpicture *subpicture; GstVaapiSubpicture *subpicture;
GstVaapiRectangle render_rect; GstVaapiRectangle render_rect;
guint seq_num; guint seq_num;
GstBuffer *rect_buffer;
GstVideoOverlayRectangle *rect; GstVideoOverlayRectangle *rect;
guint is_associated : 1; guint is_associated : 1;
}; };
@ -104,6 +105,21 @@ gst_video_overlay_rectangle_replace(GstVideoOverlayRectangle **old_rect_ptr,
GST_MINI_OBJECT_CAST(new_rect)); 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) \ #define overlay_rectangle_ref(overlay) \
gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(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->seq_num = gst_video_overlay_rectangle_get_seqnum(rect);
overlay->rect = gst_video_overlay_rectangle_ref(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( overlay->subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle(
GST_VAAPI_OBJECT_DISPLAY(context), rect); GST_VAAPI_OBJECT_DISPLAY(context), rect);
if (!overlay->subpicture) if (!overlay->subpicture)
@ -177,6 +198,7 @@ error:
static void static void
overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay) overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay)
{ {
gst_buffer_replace(&overlay->rect_buffer, NULL);
gst_video_overlay_rectangle_unref(overlay->rect); gst_video_overlay_rectangle_unref(overlay->rect);
if (overlay->subpicture) { if (overlay->subpicture) {
@ -233,9 +255,18 @@ static gboolean
overlay_rectangle_changed_pixels(GstVaapiOverlayRectangle *overlay, overlay_rectangle_changed_pixels(GstVaapiOverlayRectangle *overlay,
GstVideoOverlayRectangle *rect) GstVideoOverlayRectangle *rect)
{ {
guint width, height, stride, flags;
GstBuffer *buffer;
if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum(rect)) if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum(rect))
return FALSE; 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 static gboolean