2010-04-23 15:59:31 +00:00
|
|
|
/*
|
|
|
|
* gstvaapicontext.c - VA context abstraction
|
|
|
|
*
|
2012-01-16 09:41:10 +00:00
|
|
|
* Copyright (C) 2010-2011 Splitted-Desktop Systems
|
2013-11-22 04:57:18 +00:00
|
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
|
2014-01-22 17:54:14 +00:00
|
|
|
* Copyright (C) 2011-2014 Intel Corporation
|
2013-11-22 04:57:18 +00:00
|
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
|
2010-04-23 15:59:31 +00:00
|
|
|
*
|
2010-05-03 07:07:27 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
|
|
* of the License, or (at your option) any later version.
|
2010-04-23 15:59:31 +00:00
|
|
|
*
|
2010-05-03 07:07:27 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2010-04-23 15:59:31 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2010-05-03 07:07:27 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2010-04-23 15:59:31 +00:00
|
|
|
*
|
2010-05-03 07:07:27 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free
|
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301 USA
|
2010-04-23 15:59:31 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:gstvaapicontext
|
|
|
|
* @short_description: VA context abstraction
|
|
|
|
*/
|
|
|
|
|
2012-01-30 17:12:59 +00:00
|
|
|
#include "sysdeps.h"
|
2010-04-23 15:59:31 +00:00
|
|
|
#include "gstvaapicompat.h"
|
|
|
|
#include "gstvaapicontext.h"
|
2014-01-23 08:41:07 +00:00
|
|
|
#include "gstvaapidisplay_priv.h"
|
2013-04-30 15:22:15 +00:00
|
|
|
#include "gstvaapiobject_priv.h"
|
2011-12-13 15:53:15 +00:00
|
|
|
#include "gstvaapisurface.h"
|
|
|
|
#include "gstvaapisurface_priv.h"
|
2010-04-23 15:59:31 +00:00
|
|
|
#include "gstvaapisurfacepool.h"
|
2013-04-03 09:37:44 +00:00
|
|
|
#include "gstvaapisurfaceproxy.h"
|
2013-05-03 09:01:12 +00:00
|
|
|
#include "gstvaapivideopool_priv.h"
|
2011-12-14 13:35:13 +00:00
|
|
|
#include "gstvaapiimage.h"
|
|
|
|
#include "gstvaapisubpicture.h"
|
2010-04-23 15:59:31 +00:00
|
|
|
#include "gstvaapiutils.h"
|
|
|
|
|
|
|
|
#define DEBUG 1
|
|
|
|
#include "gstvaapidebug.h"
|
|
|
|
|
2011-12-14 13:35:13 +00:00
|
|
|
typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
|
2014-01-23 08:27:38 +00:00
|
|
|
struct _GstVaapiOverlayRectangle
|
|
|
|
{
|
|
|
|
GstVaapiContext *context;
|
|
|
|
GstVaapiSubpicture *subpicture;
|
|
|
|
GstVaapiRectangle render_rect;
|
|
|
|
guint seq_num;
|
|
|
|
guint layer_id;
|
|
|
|
GstBuffer *rect_buffer;
|
|
|
|
GstVideoOverlayRectangle *rect;
|
|
|
|
guint is_associated:1;
|
2011-12-14 13:35:13 +00:00
|
|
|
};
|
|
|
|
|
2013-01-10 17:42:37 +00:00
|
|
|
static inline void
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_video_overlay_rectangle_replace (GstVideoOverlayRectangle ** old_rect_ptr,
|
|
|
|
GstVideoOverlayRectangle * new_rect)
|
2013-01-10 17:42:37 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_mini_object_replace ((GstMiniObject **) old_rect_ptr,
|
|
|
|
GST_MINI_OBJECT_CAST (new_rect));
|
2013-01-10 17:42:37 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 12:41:39 +00:00
|
|
|
#define overlay_rectangle_ref(overlay) \
|
|
|
|
gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay))
|
|
|
|
|
|
|
|
#define overlay_rectangle_unref(overlay) \
|
|
|
|
gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(overlay))
|
|
|
|
|
|
|
|
#define overlay_rectangle_replace(old_overlay_ptr, new_overlay) \
|
|
|
|
gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_overlay_ptr), \
|
|
|
|
(GstVaapiMiniObject *)(new_overlay))
|
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
static void overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay);
|
2013-01-10 12:41:39 +00:00
|
|
|
|
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay);
|
2013-01-10 12:41:39 +00:00
|
|
|
|
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay);
|
2013-01-10 12:41:39 +00:00
|
|
|
|
|
|
|
static inline const GstVaapiMiniObjectClass *
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_class (void)
|
2013-01-10 12:41:39 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
static const GstVaapiMiniObjectClass GstVaapiOverlayRectangleClass = {
|
|
|
|
sizeof (GstVaapiOverlayRectangle),
|
|
|
|
(GDestroyNotify) overlay_rectangle_finalize
|
|
|
|
};
|
|
|
|
return &GstVaapiOverlayRectangleClass;
|
2013-01-10 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 13:35:13 +00:00
|
|
|
static GstVaapiOverlayRectangle *
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_new (GstVideoOverlayRectangle * rect,
|
|
|
|
GstVaapiContext * context, guint layer_id)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiOverlayRectangle *overlay;
|
|
|
|
GstVaapiRectangle *render_rect;
|
|
|
|
guint width, height, flags;
|
|
|
|
gint x, y;
|
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.
2013-01-11 10:12:26 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay = (GstVaapiOverlayRectangle *)
|
|
|
|
gst_vaapi_mini_object_new0 (overlay_rectangle_class ());
|
|
|
|
if (!overlay)
|
|
|
|
return NULL;
|
2013-01-10 12:41:39 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay->context = context;
|
|
|
|
overlay->seq_num = gst_video_overlay_rectangle_get_seqnum (rect);
|
|
|
|
overlay->layer_id = layer_id;
|
|
|
|
overlay->rect = gst_video_overlay_rectangle_ref (rect);
|
|
|
|
|
|
|
|
flags = gst_video_overlay_rectangle_get_flags (rect);
|
|
|
|
gst_buffer_replace (&overlay->rect_buffer,
|
|
|
|
gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags));
|
|
|
|
if (!overlay->rect_buffer)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
overlay->subpicture =
|
|
|
|
gst_vaapi_subpicture_new_from_overlay_rectangle (GST_VAAPI_OBJECT_DISPLAY
|
|
|
|
(context), rect);
|
|
|
|
if (!overlay->subpicture)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
gst_video_overlay_rectangle_get_render_rectangle (rect,
|
|
|
|
&x, &y, &width, &height);
|
|
|
|
render_rect = &overlay->render_rect;
|
|
|
|
render_rect->x = x;
|
|
|
|
render_rect->y = y;
|
|
|
|
render_rect->width = width;
|
|
|
|
render_rect->height = height;
|
|
|
|
return overlay;
|
2013-01-10 12:41:39 +00:00
|
|
|
|
|
|
|
error:
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_unref (overlay);
|
|
|
|
return NULL;
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_buffer_replace (&overlay->rect_buffer, NULL);
|
|
|
|
gst_video_overlay_rectangle_unref (overlay->rect);
|
2013-01-10 17:42:37 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (overlay->subpicture) {
|
|
|
|
overlay_rectangle_deassociate (overlay);
|
|
|
|
gst_vaapi_object_unref (overlay->subpicture);
|
|
|
|
overlay->subpicture = NULL;
|
|
|
|
}
|
2013-01-10 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay)
|
2013-01-10 12:41:39 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiSubpicture *const subpicture = overlay->subpicture;
|
|
|
|
GPtrArray *const surfaces = overlay->context->surfaces;
|
|
|
|
guint i, n_associated;
|
|
|
|
|
|
|
|
if (overlay->is_associated)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
n_associated = 0;
|
|
|
|
for (i = 0; i < surfaces->len; i++) {
|
|
|
|
GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
|
|
|
|
if (gst_vaapi_surface_associate_subpicture (surface, subpicture,
|
|
|
|
NULL, &overlay->render_rect))
|
|
|
|
n_associated++;
|
|
|
|
}
|
2013-01-10 12:41:39 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay->is_associated = TRUE;
|
|
|
|
return n_associated == surfaces->len;
|
2013-01-10 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay)
|
2013-01-10 12:41:39 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiSubpicture *const subpicture = overlay->subpicture;
|
|
|
|
GPtrArray *const surfaces = overlay->context->surfaces;
|
|
|
|
guint i, n_associated;
|
2013-01-10 12:41:39 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!overlay->is_associated)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
n_associated = surfaces->len;
|
|
|
|
for (i = 0; i < surfaces->len; i++) {
|
|
|
|
GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
|
|
|
|
if (gst_vaapi_surface_deassociate_subpicture (surface, subpicture))
|
|
|
|
n_associated--;
|
|
|
|
}
|
|
|
|
|
|
|
|
overlay->is_associated = FALSE;
|
|
|
|
return n_associated == 0;
|
2013-01-10 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 17:42:37 +00:00
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_changed_pixels (GstVaapiOverlayRectangle * overlay,
|
|
|
|
GstVideoOverlayRectangle * rect)
|
2013-01-10 17:42:37 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
guint flags;
|
|
|
|
GstBuffer *buffer;
|
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.
2013-01-11 10:12:26 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum (rect))
|
|
|
|
return FALSE;
|
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.
2013-01-11 10:12:26 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
flags =
|
|
|
|
to_GstVideoOverlayFormatFlags (gst_vaapi_subpicture_get_flags
|
|
|
|
(overlay->subpicture));
|
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.
2013-01-11 10:12:26 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
buffer = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags);
|
|
|
|
if (!buffer)
|
|
|
|
return FALSE;
|
2012-09-04 12:12:18 +00:00
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
2014-01-23 08:27:38 +00:00
|
|
|
{
|
|
|
|
const guint n_blocks = gst_buffer_n_memory (buffer);
|
|
|
|
gsize ofs;
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
if (buffer == overlay->rect_buffer)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (n_blocks != gst_buffer_n_memory (overlay->rect_buffer))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (i = 0; i < n_blocks; i++) {
|
|
|
|
GstMemory *const mem1 = gst_buffer_peek_memory (buffer, i);
|
|
|
|
GstMemory *const mem2 = gst_buffer_peek_memory (overlay->rect_buffer, i);
|
|
|
|
if (!gst_memory_is_span (mem1, mem2, &ofs))
|
|
|
|
return FALSE;
|
2012-09-04 12:12:18 +00:00
|
|
|
}
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
2012-09-04 12:12:18 +00:00
|
|
|
#else
|
2014-01-23 08:27:38 +00:00
|
|
|
if (GST_BUFFER_DATA (overlay->rect_buffer) != GST_BUFFER_DATA (buffer))
|
|
|
|
return FALSE;
|
2012-09-04 12:12:18 +00:00
|
|
|
#endif
|
2014-01-23 08:27:38 +00:00
|
|
|
return TRUE;
|
2013-01-10 17:42:37 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 10:53:05 +00:00
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_changed_render_rect (GstVaapiOverlayRectangle * overlay,
|
|
|
|
GstVideoOverlayRectangle * rect)
|
2013-01-11 10:53:05 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiRectangle *const render_rect = &overlay->render_rect;
|
|
|
|
guint width, height;
|
|
|
|
gint x, y;
|
2013-01-11 10:53:05 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_video_overlay_rectangle_get_render_rectangle (rect,
|
|
|
|
&x, &y, &width, &height);
|
2013-01-11 10:53:05 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (x == render_rect->x &&
|
|
|
|
y == render_rect->y &&
|
|
|
|
width == render_rect->width && height == render_rect->height)
|
|
|
|
return FALSE;
|
2013-01-11 10:53:05 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
render_rect->x = x;
|
|
|
|
render_rect->y = y;
|
|
|
|
render_rect->width = width;
|
|
|
|
render_rect->height = height;
|
|
|
|
return TRUE;
|
2013-01-11 10:53:05 +00:00
|
|
|
}
|
|
|
|
|
2012-05-15 08:24:08 +00:00
|
|
|
static inline gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_update_global_alpha (GstVaapiOverlayRectangle * overlay,
|
|
|
|
GstVideoOverlayRectangle * rect)
|
2012-05-15 08:24:08 +00:00
|
|
|
{
|
2012-07-20 10:36:33 +00:00
|
|
|
#ifdef HAVE_GST_VIDEO_OVERLAY_HWCAPS
|
2014-01-23 08:27:38 +00:00
|
|
|
const guint flags = gst_video_overlay_rectangle_get_flags (rect);
|
|
|
|
if (!(flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA))
|
|
|
|
return TRUE;
|
2012-07-20 10:36:33 +00:00
|
|
|
#endif
|
2014-01-23 08:27:38 +00:00
|
|
|
return gst_vaapi_subpicture_set_global_alpha (overlay->subpicture,
|
|
|
|
gst_video_overlay_rectangle_get_global_alpha (rect));
|
2012-05-15 08:24:08 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 17:42:37 +00:00
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_rectangle_update (GstVaapiOverlayRectangle * overlay,
|
|
|
|
GstVideoOverlayRectangle * rect, gboolean * reassociate_ptr)
|
2013-01-10 17:42:37 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
if (overlay_rectangle_changed_pixels (overlay, rect))
|
|
|
|
return FALSE;
|
|
|
|
if (overlay_rectangle_changed_render_rect (overlay, rect))
|
|
|
|
*reassociate_ptr = TRUE;
|
|
|
|
if (!overlay_rectangle_update_global_alpha (overlay, rect))
|
|
|
|
return FALSE;
|
|
|
|
gst_video_overlay_rectangle_replace (&overlay->rect, rect);
|
|
|
|
return TRUE;
|
2013-01-10 17:42:37 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 12:41:39 +00:00
|
|
|
static inline GPtrArray *
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_new (void)
|
2013-01-10 12:41:39 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
return g_ptr_array_new_with_free_func (
|
|
|
|
(GDestroyNotify) gst_vaapi_mini_object_unref);
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_destroy (GPtrArray ** overlay_ptr)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GPtrArray *const overlay = *overlay_ptr;
|
2011-12-14 13:35:13 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!overlay)
|
|
|
|
return;
|
|
|
|
g_ptr_array_unref (overlay);
|
|
|
|
*overlay_ptr = NULL;
|
2013-01-10 12:41:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_clear (GPtrArray * overlay)
|
2013-01-10 12:41:39 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
if (overlay && overlay->len > 0)
|
|
|
|
g_ptr_array_remove_range (overlay, 0, overlay->len);
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 17:42:37 +00:00
|
|
|
static GstVaapiOverlayRectangle *
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_lookup (GPtrArray * overlays, GstVideoOverlayRectangle * rect)
|
2013-01-10 17:42:37 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
guint i;
|
2013-01-10 17:42:37 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
for (i = 0; i < overlays->len; i++) {
|
|
|
|
GstVaapiOverlayRectangle *const overlay = g_ptr_array_index (overlays, i);
|
2013-01-10 17:42:37 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (overlay->rect == rect)
|
|
|
|
return overlay;
|
|
|
|
}
|
|
|
|
return NULL;
|
2013-01-10 17:42:37 +00:00
|
|
|
}
|
|
|
|
|
2013-01-11 14:19:45 +00:00
|
|
|
static gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_reassociate (GPtrArray * overlays)
|
2013-01-11 14:19:45 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
guint i;
|
2013-01-11 14:19:45 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
for (i = 0; i < overlays->len; i++)
|
|
|
|
overlay_rectangle_deassociate (g_ptr_array_index (overlays, i));
|
2013-01-11 14:19:45 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
for (i = 0; i < overlays->len; i++) {
|
|
|
|
if (!overlay_rectangle_associate (g_ptr_array_index (overlays, i)))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2013-01-11 14:19:45 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 13:35:13 +00:00
|
|
|
static void
|
2014-01-23 08:41:07 +00:00
|
|
|
context_clear_overlay (GstVaapiContext * context)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_clear (context->overlays[0]);
|
|
|
|
overlay_clear (context->overlays[1]);
|
|
|
|
context->overlay_id = 0;
|
2013-01-10 17:42:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy_overlay (GstVaapiContext * context)
|
2013-01-10 17:42:37 +00:00
|
|
|
{
|
2014-01-23 08:41:07 +00:00
|
|
|
context_clear_overlay (context);
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
|
|
|
|
2010-04-23 15:59:31 +00:00
|
|
|
static void
|
2014-01-23 08:41:07 +00:00
|
|
|
unref_surface_cb (GstVaapiSurface * surface)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_surface_set_parent_context (surface, NULL);
|
|
|
|
gst_vaapi_object_unref (surface);
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy_surfaces (GstVaapiContext * context)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy_overlay (context);
|
2011-12-14 13:35:13 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (context->surfaces) {
|
2014-01-23 08:41:07 +00:00
|
|
|
g_ptr_array_unref (context->surfaces);
|
2014-01-23 08:27:38 +00:00
|
|
|
context->surfaces = NULL;
|
|
|
|
}
|
|
|
|
gst_vaapi_video_pool_replace (&context->surfaces_pool, NULL);
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy (GstVaapiContext * context)
|
2014-01-23 08:27:38 +00:00
|
|
|
{
|
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (context);
|
|
|
|
VAContextID context_id;
|
|
|
|
VAStatus status;
|
|
|
|
|
|
|
|
context_id = GST_VAAPI_OBJECT_ID (context);
|
2014-01-23 08:41:07 +00:00
|
|
|
GST_DEBUG ("context 0x%08x", context_id);
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
if (context_id != VA_INVALID_ID) {
|
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaDestroyContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
|
|
|
context_id);
|
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaDestroyContext()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
GST_WARNING ("failed to destroy context 0x%08x", context_id);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_OBJECT_ID (context) = VA_INVALID_ID;
|
|
|
|
}
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (context->va_config != VA_INVALID_ID) {
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaDestroyConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_config);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaDestroyConfig()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
GST_WARNING ("failed to destroy config 0x%08x", context->va_config);
|
|
|
|
context->va_config = VA_INVALID_ID;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 13:35:13 +00:00
|
|
|
static gboolean
|
2014-01-23 08:41:07 +00:00
|
|
|
context_create_overlay (GstVaapiContext * context)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!context->overlays[0] || !context->overlays[1])
|
|
|
|
return FALSE;
|
2013-01-10 12:41:39 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
context_clear_overlay (context);
|
2014-01-23 08:27:38 +00:00
|
|
|
return TRUE;
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
|
|
|
|
2010-04-23 15:59:31 +00:00
|
|
|
static gboolean
|
2014-01-23 08:41:07 +00:00
|
|
|
context_create_surfaces (GstVaapiContext * context)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
const GstVaapiContextInfo *const cip = &context->info;
|
|
|
|
GstVideoInfo vi;
|
|
|
|
GstVaapiSurface *surface;
|
|
|
|
guint i, num_surfaces;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
/* Number of scratch surfaces beyond those used as reference */
|
|
|
|
const guint SCRATCH_SURFACES_COUNT = 4;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (!context_create_overlay (context))
|
2014-01-23 08:27:38 +00:00
|
|
|
return FALSE;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!context->surfaces) {
|
2014-01-23 08:41:07 +00:00
|
|
|
context->surfaces = g_ptr_array_new_full (num_surfaces,
|
|
|
|
(GDestroyNotify) unref_surface_cb);
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!context->surfaces)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!context->surfaces_pool) {
|
|
|
|
gst_video_info_set_format (&vi, GST_VIDEO_FORMAT_ENCODED,
|
|
|
|
cip->width, cip->height);
|
|
|
|
context->surfaces_pool =
|
|
|
|
gst_vaapi_surface_pool_new (GST_VAAPI_OBJECT_DISPLAY (context), &vi);
|
|
|
|
if (!context->surfaces_pool)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
gst_vaapi_video_pool_set_capacity (context->surfaces_pool, num_surfaces);
|
|
|
|
|
|
|
|
for (i = context->surfaces->len; i < num_surfaces; i++) {
|
|
|
|
surface = gst_vaapi_surface_new (GST_VAAPI_OBJECT_DISPLAY (context),
|
|
|
|
GST_VAAPI_CHROMA_TYPE_YUV420, cip->width, cip->height);
|
|
|
|
if (!surface)
|
|
|
|
return FALSE;
|
|
|
|
gst_vaapi_surface_set_parent_context (surface, context);
|
|
|
|
g_ptr_array_add (context->surfaces, surface);
|
|
|
|
if (!gst_vaapi_video_pool_add_object (context->surfaces_pool, surface))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2014-01-23 08:41:07 +00:00
|
|
|
context_create (GstVaapiContext * context)
|
2014-01-23 08:27:38 +00:00
|
|
|
{
|
|
|
|
const GstVaapiContextInfo *const cip = &context->info;
|
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (context);
|
|
|
|
guint va_rate_control;
|
|
|
|
VAConfigAttrib attribs[2];
|
|
|
|
guint num_attribs;
|
|
|
|
VAContextID context_id;
|
|
|
|
VASurfaceID surface_id;
|
|
|
|
VAStatus status;
|
|
|
|
GArray *surfaces = NULL;
|
|
|
|
gboolean success = FALSE;
|
|
|
|
guint i;
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (!context->surfaces && !context_create_surfaces (context))
|
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
surfaces = g_array_sized_new (FALSE,
|
|
|
|
FALSE, sizeof (VASurfaceID), context->surfaces->len);
|
|
|
|
if (!surfaces)
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
for (i = 0; i < context->surfaces->len; i++) {
|
|
|
|
GstVaapiSurface *const surface = g_ptr_array_index (context->surfaces, i);
|
|
|
|
if (!surface)
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
surface_id = GST_VAAPI_OBJECT_ID (surface);
|
|
|
|
g_array_append_val (surfaces, surface_id);
|
|
|
|
}
|
2014-01-23 08:41:07 +00:00
|
|
|
g_assert (surfaces->len == context->surfaces->len);
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
if (!cip->profile || !cip->entrypoint)
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
context->va_profile = gst_vaapi_profile_get_va_profile (cip->profile);
|
|
|
|
context->va_entrypoint =
|
|
|
|
gst_vaapi_entrypoint_get_va_entrypoint (cip->entrypoint);
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
num_attribs = 0;
|
|
|
|
attribs[num_attribs++].type = VAConfigAttribRTFormat;
|
|
|
|
if (cip->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE)
|
|
|
|
attribs[num_attribs++].type = VAConfigAttribRateControl;
|
|
|
|
|
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaGetConfigAttributes (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_profile, context->va_entrypoint, attribs, num_attribs);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaGetConfigAttributes()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!(attribs[0].value & VA_RT_FORMAT_YUV420))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
if (cip->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE) {
|
|
|
|
va_rate_control = from_GstVaapiRateControl (cip->rc_mode);
|
|
|
|
if (va_rate_control == VA_RC_NONE)
|
|
|
|
attribs[1].value = VA_RC_NONE;
|
|
|
|
if ((attribs[1].value & va_rate_control) != va_rate_control) {
|
|
|
|
GST_ERROR ("unsupported %s rate control",
|
|
|
|
string_of_VARateControl (va_rate_control));
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2013-07-12 14:07:59 +00:00
|
|
|
}
|
2014-01-23 08:27:38 +00:00
|
|
|
attribs[1].value = va_rate_control;
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_profile, context->va_entrypoint, attribs, num_attribs,
|
|
|
|
&context->va_config);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaCreateConfig()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_config, cip->width, cip->height, VA_PROGRESSIVE,
|
2014-01-23 08:27:38 +00:00
|
|
|
(VASurfaceID *) surfaces->data, surfaces->len, &context_id);
|
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaCreateContext()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
GST_DEBUG ("context 0x%08x", context_id);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_OBJECT_ID (context) = context_id;
|
|
|
|
success = TRUE;
|
2014-01-23 08:41:07 +00:00
|
|
|
|
|
|
|
cleanup:
|
2014-01-23 08:27:38 +00:00
|
|
|
if (surfaces)
|
|
|
|
g_array_free (surfaces, TRUE);
|
|
|
|
return success;
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2013-04-30 15:22:15 +00:00
|
|
|
static inline void
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_init (GstVaapiContext * context,
|
|
|
|
const GstVaapiContextInfo * cip)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
context->info = *cip;
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_config = VA_INVALID_ID;
|
2014-01-23 08:27:38 +00:00
|
|
|
context->overlays[0] = overlay_new ();
|
|
|
|
context->overlays[1] = overlay_new ();
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_finalize (GstVaapiContext * context)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_destroy (&context->overlays[0]);
|
|
|
|
overlay_destroy (&context->overlays[1]);
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy (context);
|
|
|
|
context_destroy_surfaces (context);
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
GST_VAAPI_OBJECT_DEFINE_CLASS (GstVaapiContext, gst_vaapi_context);
|
2010-04-23 15:59:31 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_new:
|
|
|
|
* @display: a #GstVaapiDisplay
|
2012-09-10 16:15:02 +00:00
|
|
|
* @cip: a pointer to the #GstVaapiContextInfo
|
|
|
|
*
|
|
|
|
* Creates a new #GstVaapiContext with the configuration specified by
|
|
|
|
* @cip, thus including profile, entry-point, encoded size and maximum
|
|
|
|
* number of reference frames reported by the bitstream.
|
|
|
|
*
|
|
|
|
* Return value: the newly allocated #GstVaapiContext object
|
|
|
|
*/
|
|
|
|
GstVaapiContext *
|
2014-01-23 08:41:07 +00:00
|
|
|
gst_vaapi_context_new (GstVaapiDisplay * display,
|
2014-01-23 08:27:38 +00:00
|
|
|
const GstVaapiContextInfo * cip)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiContext *context;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
g_return_val_if_fail (cip->profile, NULL);
|
|
|
|
g_return_val_if_fail (cip->entrypoint, NULL);
|
|
|
|
g_return_val_if_fail (cip->width > 0, NULL);
|
|
|
|
g_return_val_if_fail (cip->height > 0, NULL);
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
context = gst_vaapi_object_new (gst_vaapi_context_class (), display);
|
|
|
|
if (!context)
|
|
|
|
return NULL;
|
2013-04-30 15:22:15 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_init (context, cip);
|
2014-01-23 08:41:07 +00:00
|
|
|
if (!context_create (context))
|
2014-01-23 08:27:38 +00:00
|
|
|
goto error;
|
|
|
|
return context;
|
2013-04-30 15:22:15 +00:00
|
|
|
|
|
|
|
error:
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_object_unref (context);
|
|
|
|
return NULL;
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_reset:
|
|
|
|
* @context: a #GstVaapiContext
|
2013-04-30 15:22:15 +00:00
|
|
|
* @new_cip: a pointer to the new #GstVaapiContextInfo details
|
2012-09-10 16:15:02 +00:00
|
|
|
*
|
2013-04-30 15:22:15 +00:00
|
|
|
* Resets @context to the configuration specified by @new_cip, thus
|
2012-09-10 16:15:02 +00:00
|
|
|
* including profile, entry-point, encoded size and maximum number of
|
|
|
|
* reference frames reported by the bitstream.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE on success
|
|
|
|
*/
|
|
|
|
gboolean
|
2014-01-23 08:41:07 +00:00
|
|
|
gst_vaapi_context_reset (GstVaapiContext * context,
|
2014-01-23 08:27:38 +00:00
|
|
|
const GstVaapiContextInfo * new_cip)
|
|
|
|
{
|
|
|
|
GstVaapiContextInfo *const cip = &context->info;
|
2014-01-23 08:41:07 +00:00
|
|
|
gboolean size_changed, config_changed;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
|
|
|
size_changed = cip->width != new_cip->width || cip->height != new_cip->height;
|
|
|
|
if (size_changed) {
|
|
|
|
cip->width = new_cip->width;
|
|
|
|
cip->height = new_cip->height;
|
|
|
|
}
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
config_changed = cip->profile != new_cip->profile ||
|
2014-01-23 08:27:38 +00:00
|
|
|
cip->entrypoint != new_cip->entrypoint;
|
2014-01-23 08:41:07 +00:00
|
|
|
if (config_changed) {
|
2014-01-23 08:27:38 +00:00
|
|
|
cip->profile = new_cip->profile;
|
|
|
|
cip->entrypoint = new_cip->entrypoint;
|
|
|
|
}
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
switch (new_cip->entrypoint) {
|
|
|
|
case GST_VAAPI_ENTRYPOINT_SLICE_ENCODE:
|
|
|
|
if (cip->rc_mode != new_cip->rc_mode) {
|
|
|
|
cip->rc_mode = new_cip->rc_mode;
|
|
|
|
config_changed = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (size_changed)
|
|
|
|
context_destroy_surfaces (context);
|
|
|
|
if (config_changed)
|
|
|
|
context_destroy (context);
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (size_changed && !context_create_surfaces (context))
|
|
|
|
return FALSE;
|
|
|
|
if (config_changed && !context_create (context))
|
2014-01-23 08:27:38 +00:00
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_get_id:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
*
|
|
|
|
* Returns the underlying VAContextID of the @context.
|
|
|
|
*
|
|
|
|
* Return value: the underlying VA context id
|
|
|
|
*/
|
|
|
|
GstVaapiID
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_get_id (GstVaapiContext * context)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
g_return_val_if_fail (context != NULL, VA_INVALID_ID);
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
return GST_VAAPI_OBJECT_ID (context);
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2013-04-03 09:37:44 +00:00
|
|
|
/**
|
|
|
|
* gst_vaapi_context_get_surface_proxy:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
*
|
|
|
|
* Acquires a free surface, wrapped into a #GstVaapiSurfaceProxy. The
|
|
|
|
* returned surface will be automatically released when the proxy is
|
|
|
|
* destroyed. So, it is enough to call gst_vaapi_surface_proxy_unref()
|
|
|
|
* after usage.
|
|
|
|
*
|
|
|
|
* This function returns %NULL if there is no free surface available
|
|
|
|
* in the pool. The surfaces are pre-allocated during context creation
|
|
|
|
* though.
|
|
|
|
*
|
|
|
|
* Return value: a free surface, or %NULL if none is available
|
|
|
|
*/
|
|
|
|
GstVaapiSurfaceProxy *
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_get_surface_proxy (GstVaapiContext * context)
|
2013-04-03 09:37:44 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
g_return_val_if_fail (context != NULL, NULL);
|
2013-04-03 09:37:44 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
return
|
2014-01-23 08:41:07 +00:00
|
|
|
gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL
|
|
|
|
(context->surfaces_pool));
|
2013-04-03 09:37:44 +00:00
|
|
|
}
|
|
|
|
|
2010-05-15 05:36:15 +00:00
|
|
|
/**
|
|
|
|
* gst_vaapi_context_get_surface_count:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
*
|
|
|
|
* Retrieves the number of free surfaces left in the pool.
|
|
|
|
*
|
|
|
|
* Return value: the number of free surfaces available in the pool
|
|
|
|
*/
|
|
|
|
guint
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_get_surface_count (GstVaapiContext * context)
|
2010-05-15 05:36:15 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
g_return_val_if_fail (context != NULL, 0);
|
2010-05-15 05:36:15 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
return gst_vaapi_video_pool_get_size (context->surfaces_pool);
|
2010-05-15 05:36:15 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 13:35:13 +00:00
|
|
|
/**
|
|
|
|
* gst_vaapi_context_apply_composition:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
* @composition: a #GstVideoOverlayComposition
|
|
|
|
*
|
|
|
|
* Applies video composition planes to all surfaces bound to @context.
|
|
|
|
* This helper function resets any additional subpictures the user may
|
|
|
|
* have associated himself. A %NULL @composition will also clear all
|
|
|
|
* the existing subpictures.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE if all composition planes could be applied,
|
|
|
|
* %FALSE otherwise
|
|
|
|
*/
|
|
|
|
gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_apply_composition (GstVaapiContext * context,
|
|
|
|
GstVideoOverlayComposition * composition)
|
2011-12-14 13:35:13 +00:00
|
|
|
{
|
2014-01-23 08:27:38 +00:00
|
|
|
GPtrArray *curr_overlay, *next_overlay;
|
|
|
|
guint i, n_rectangles;
|
|
|
|
gboolean reassociate = FALSE;
|
2011-12-14 13:35:13 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
g_return_val_if_fail (context != NULL, FALSE);
|
2011-12-14 13:35:13 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!context->surfaces)
|
|
|
|
return FALSE;
|
2011-12-14 13:35:13 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!composition) {
|
2014-01-23 08:41:07 +00:00
|
|
|
context_clear_overlay (context);
|
2014-01-23 08:27:38 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2013-01-10 12:41:39 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
curr_overlay = context->overlays[context->overlay_id];
|
|
|
|
next_overlay = context->overlays[context->overlay_id ^ 1];
|
|
|
|
overlay_clear (next_overlay);
|
|
|
|
|
|
|
|
n_rectangles = gst_video_overlay_composition_n_rectangles (composition);
|
|
|
|
for (i = 0; i < n_rectangles; i++) {
|
|
|
|
GstVideoOverlayRectangle *const rect =
|
|
|
|
gst_video_overlay_composition_get_rectangle (composition, i);
|
|
|
|
GstVaapiOverlayRectangle *overlay;
|
|
|
|
|
|
|
|
overlay = overlay_lookup (curr_overlay, rect);
|
|
|
|
if (overlay && overlay_rectangle_update (overlay, rect, &reassociate)) {
|
|
|
|
overlay_rectangle_ref (overlay);
|
|
|
|
if (overlay->layer_id != i)
|
|
|
|
reassociate = TRUE;
|
|
|
|
} else {
|
|
|
|
overlay = overlay_rectangle_new (rect, context, i);
|
|
|
|
if (!overlay) {
|
|
|
|
GST_WARNING ("could not create VA overlay rectangle");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
reassociate = TRUE;
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
2014-01-23 08:27:38 +00:00
|
|
|
g_ptr_array_add (next_overlay, overlay);
|
|
|
|
}
|
2013-01-10 17:42:37 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
overlay_clear (curr_overlay);
|
|
|
|
context->overlay_id ^= 1;
|
2013-01-11 14:19:45 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (reassociate && !overlay_reassociate (next_overlay))
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
2013-01-10 12:41:39 +00:00
|
|
|
|
|
|
|
error:
|
2014-01-23 08:41:07 +00:00
|
|
|
context_clear_overlay (context);
|
2014-01-23 08:27:38 +00:00
|
|
|
return FALSE;
|
2011-12-14 13:35:13 +00:00
|
|
|
}
|
2014-01-21 17:35:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_get_attribute:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
* @type: a VA config attribute type
|
|
|
|
* @out_value_ptr: return location for the config attribute value
|
|
|
|
*
|
|
|
|
* Determines the value for the VA config attribute @type.
|
|
|
|
*
|
|
|
|
* Note: this function only returns success if the VA driver does
|
|
|
|
* actually know about this config attribute type and that it returned
|
|
|
|
* a valid value for it.
|
|
|
|
*
|
|
|
|
* Return value: %TRUE if the VA driver knows about the requested
|
|
|
|
* config attribute and returned a valid value, %FALSE otherwise
|
|
|
|
*/
|
|
|
|
gboolean
|
2014-01-23 08:27:38 +00:00
|
|
|
gst_vaapi_context_get_attribute (GstVaapiContext * context,
|
|
|
|
VAConfigAttribType type, guint * out_value_ptr)
|
|
|
|
{
|
|
|
|
VAConfigAttrib attrib;
|
|
|
|
VAStatus status;
|
|
|
|
|
|
|
|
g_return_val_if_fail (context != NULL, FALSE);
|
|
|
|
|
|
|
|
GST_VAAPI_OBJECT_LOCK_DISPLAY (context);
|
|
|
|
attrib.type = type;
|
|
|
|
status = vaGetConfigAttributes (GST_VAAPI_OBJECT_VADISPLAY (context),
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_profile, context->va_entrypoint, &attrib, 1);
|
2014-01-23 08:27:38 +00:00
|
|
|
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (context);
|
2014-01-23 08:41:07 +00:00
|
|
|
if (!vaapi_check_status (status, "vaGetConfigAttributes()"))
|
2014-01-23 08:27:38 +00:00
|
|
|
return FALSE;
|
2014-01-21 17:35:17 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (out_value_ptr)
|
|
|
|
*out_value_ptr = attrib.value;
|
|
|
|
return TRUE;
|
2014-01-21 17:35:17 +00:00
|
|
|
}
|