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 09:59:20 +00:00
|
|
|
#include "gstvaapicontext_overlay.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"
|
2010-04-23 15:59:31 +00:00
|
|
|
#include "gstvaapiutils.h"
|
2014-01-23 17:41:24 +00:00
|
|
|
#include "gstvaapiutils_core.h"
|
2010-04-23 15:59:31 +00:00
|
|
|
|
|
|
|
#define DEBUG 1
|
|
|
|
#include "gstvaapidebug.h"
|
|
|
|
|
2014-04-25 11:45:31 +00:00
|
|
|
/* Define default VA surface chroma format to YUV 4:2:0 */
|
|
|
|
#define DEFAULT_CHROMA_TYPE (GST_VAAPI_CHROMA_TYPE_YUV420)
|
|
|
|
|
2014-05-03 13:56:51 +00:00
|
|
|
/* Number of scratch surfaces beyond those used as reference */
|
|
|
|
#define SCRATCH_SURFACES_COUNT (4)
|
|
|
|
|
2016-02-18 18:32:58 +00:00
|
|
|
static gboolean
|
|
|
|
ensure_formats (GstVaapiContext * context)
|
|
|
|
{
|
|
|
|
if (G_LIKELY (context->formats))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
context->formats =
|
|
|
|
gst_vaapi_get_surface_formats (GST_VAAPI_OBJECT_DISPLAY (context),
|
|
|
|
context->va_config);
|
|
|
|
return (context->formats != NULL);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-01-23 17:41:24 +00:00
|
|
|
static inline gboolean
|
|
|
|
context_get_attribute (GstVaapiContext * context, VAConfigAttribType type,
|
|
|
|
guint * out_value_ptr)
|
|
|
|
{
|
|
|
|
return gst_vaapi_get_config_attribute (GST_VAAPI_OBJECT_DISPLAY (context),
|
|
|
|
context->va_profile, context->va_entrypoint, type, out_value_ptr);
|
|
|
|
}
|
|
|
|
|
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 09:59:20 +00:00
|
|
|
gst_vaapi_context_overlay_reset (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
|
|
|
}
|
2016-02-18 18:32:58 +00:00
|
|
|
|
|
|
|
if (context->formats) {
|
|
|
|
g_array_unref (context->formats);
|
|
|
|
context->formats = NULL;
|
|
|
|
}
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2014-05-03 13:56:51 +00:00
|
|
|
context_ensure_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;
|
2014-05-03 13:56:51 +00:00
|
|
|
const guint num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
|
2014-01-23 08:27:38 +00:00
|
|
|
GstVaapiSurface *surface;
|
2014-05-03 13:56:51 +00:00
|
|
|
guint i;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-05-03 13:56:51 +00:00
|
|
|
for (i = context->surfaces->len; i < num_surfaces; i++) {
|
|
|
|
surface = gst_vaapi_surface_new (GST_VAAPI_OBJECT_DISPLAY (context),
|
|
|
|
cip->chroma_type, 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;
|
|
|
|
}
|
|
|
|
gst_vaapi_video_pool_set_capacity (context->surfaces_pool, num_surfaces);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
context_create_surfaces (GstVaapiContext * context)
|
|
|
|
{
|
|
|
|
const GstVaapiContextInfo *const cip = &context->info;
|
2016-02-03 10:04:15 +00:00
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (context);
|
2014-05-03 13:56:51 +00:00
|
|
|
guint num_surfaces;
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-01-23 09:59:20 +00:00
|
|
|
if (!gst_vaapi_context_overlay_reset (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) {
|
|
|
|
context->surfaces_pool =
|
2016-02-03 10:04:15 +00:00
|
|
|
gst_vaapi_surface_pool_new_with_chroma_type (display, cip->chroma_type,
|
|
|
|
cip->width, cip->height);
|
2015-12-08 14:14:11 +00:00
|
|
|
|
2014-01-23 08:27:38 +00:00
|
|
|
if (!context->surfaces_pool)
|
|
|
|
return FALSE;
|
|
|
|
}
|
2014-05-03 13:56:51 +00:00
|
|
|
return context_ensure_surfaces (context);
|
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);
|
|
|
|
VAContextID context_id;
|
|
|
|
VASurfaceID surface_id;
|
|
|
|
VAStatus status;
|
|
|
|
GArray *surfaces = NULL;
|
|
|
|
gboolean success = FALSE;
|
2016-12-02 00:28:07 +00:00
|
|
|
guint i;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
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
|
|
|
|
2014-01-23 12:30:41 +00:00
|
|
|
/* Create VA surfaces list for vaCreateContext() */
|
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
|
|
|
|
2016-12-02 00:28:07 +00:00
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
|
|
|
context->va_config, cip->width, cip->height, VA_PROGRESSIVE,
|
|
|
|
(VASurfaceID *) surfaces->data, surfaces->len, &context_id);
|
|
|
|
GST_VAAPI_DISPLAY_UNLOCK (display);
|
|
|
|
if (!vaapi_check_status (status, "vaCreateContext()"))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
GST_DEBUG ("context 0x%08x", context_id);
|
|
|
|
GST_VAAPI_OBJECT_ID (context) = context_id;
|
|
|
|
success = TRUE;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (surfaces)
|
|
|
|
g_array_free (surfaces, TRUE);
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
config_create (GstVaapiContext * context)
|
|
|
|
{
|
|
|
|
const GstVaapiContextInfo *const cip = &context->info;
|
|
|
|
GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (context);
|
2017-08-09 20:45:40 +00:00
|
|
|
VAConfigAttrib attribs[7], *attrib;
|
2016-12-02 00:28:07 +00:00
|
|
|
VAStatus status;
|
2017-08-08 16:52:37 +00:00
|
|
|
guint value, va_chroma_format, attrib_index;
|
2016-12-02 00:28:07 +00:00
|
|
|
|
2014-01-23 12:30:41 +00:00
|
|
|
/* Reset profile and entrypoint */
|
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
|
|
|
|
2017-08-08 16:52:37 +00:00
|
|
|
attrib_index = 0;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
|
|
|
|
2014-01-23 12:30:41 +00:00
|
|
|
/* Validate VA surface format */
|
2014-04-25 11:45:31 +00:00
|
|
|
va_chroma_format = from_GstVaapiChromaType (cip->chroma_type);
|
|
|
|
if (!va_chroma_format)
|
|
|
|
goto cleanup;
|
2014-01-23 12:30:41 +00:00
|
|
|
attrib->type = VAConfigAttribRTFormat;
|
2014-01-23 17:41:24 +00:00
|
|
|
if (!context_get_attribute (context, attrib->type, &value))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-05-10 04:23:29 +00:00
|
|
|
if (!(value & va_chroma_format)) {
|
|
|
|
GST_ERROR ("unsupported chroma format (%s)",
|
|
|
|
string_of_va_chroma_format (va_chroma_format));
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-05-10 04:23:29 +00:00
|
|
|
}
|
2014-04-25 11:45:31 +00:00
|
|
|
attrib->value = va_chroma_format;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
2014-01-23 12:30:41 +00:00
|
|
|
|
|
|
|
switch (cip->usage) {
|
2014-01-23 21:44:09 +00:00
|
|
|
#if USE_ENCODERS
|
2014-01-23 12:30:41 +00:00
|
|
|
case GST_VAAPI_CONTEXT_USAGE_ENCODE:
|
|
|
|
{
|
2014-01-23 13:01:33 +00:00
|
|
|
const GstVaapiConfigInfoEncoder *const config = &cip->config.encoder;
|
2014-01-23 21:44:09 +00:00
|
|
|
guint va_rate_control;
|
2014-01-23 13:01:33 +00:00
|
|
|
|
2014-01-23 12:30:41 +00:00
|
|
|
/* Rate control */
|
2014-01-23 13:01:33 +00:00
|
|
|
va_rate_control = from_GstVaapiRateControl (config->rc_mode);
|
2015-02-04 09:17:27 +00:00
|
|
|
if (va_rate_control != VA_RC_NONE) {
|
|
|
|
attrib->type = VAConfigAttribRateControl;
|
|
|
|
if (!context_get_attribute (context, attrib->type, &value))
|
|
|
|
goto cleanup;
|
2014-01-23 14:13:06 +00:00
|
|
|
|
2015-02-04 09:17:27 +00:00
|
|
|
if ((value & va_rate_control) != va_rate_control) {
|
|
|
|
GST_ERROR ("unsupported %s rate control",
|
|
|
|
string_of_VARateControl (va_rate_control));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
attrib->value = va_rate_control;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
2015-02-04 09:17:27 +00:00
|
|
|
}
|
2014-01-23 14:13:06 +00:00
|
|
|
/* Packed headers */
|
|
|
|
if (config->packed_headers) {
|
|
|
|
attrib->type = VAConfigAttribEncPackedHeaders;
|
2014-01-23 17:41:24 +00:00
|
|
|
if (!context_get_attribute (context, attrib->type, &value))
|
2014-01-23 14:13:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((value & config->packed_headers) != config->packed_headers) {
|
|
|
|
GST_ERROR ("unsupported packed headers 0x%08x",
|
|
|
|
config->packed_headers & ~(value & config->packed_headers));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
attrib->value = config->packed_headers;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
2014-01-23 14:13:06 +00:00
|
|
|
}
|
2015-02-04 09:17:58 +00:00
|
|
|
#if VA_CHECK_VERSION(0,37,0)
|
|
|
|
if (cip->profile == GST_VAAPI_PROFILE_JPEG_BASELINE) {
|
|
|
|
attrib->type = VAConfigAttribEncJPEG;
|
|
|
|
if (!context_get_attribute (context, attrib->type, &value))
|
|
|
|
goto cleanup;
|
2015-06-23 15:49:51 +00:00
|
|
|
attrib->value = value;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
2015-02-04 09:17:58 +00:00
|
|
|
}
|
2017-02-23 08:57:07 +00:00
|
|
|
#endif
|
|
|
|
#if VA_CHECK_VERSION(0,39,1)
|
|
|
|
if (config->roi_capability) {
|
|
|
|
VAConfigAttribValEncROI *roi_config;
|
2017-08-08 16:52:37 +00:00
|
|
|
|
2017-02-23 08:57:07 +00:00
|
|
|
attrib->type = VAConfigAttribEncROI;
|
|
|
|
if (!context_get_attribute (context, attrib->type, &value))
|
|
|
|
goto cleanup;
|
|
|
|
roi_config = (VAConfigAttribValEncROI *) & value;
|
|
|
|
if (roi_config->bits.num_roi_regions != config->roi_num_supported ||
|
2017-08-17 10:44:40 +00:00
|
|
|
VA_ROI_RC_QP_DELTA_SUPPORT (roi_config) == 0) {
|
2018-02-22 20:20:42 +00:00
|
|
|
GST_ERROR ("Mismatched ROI support: number of regions supported: %d"
|
2017-02-23 08:57:07 +00:00
|
|
|
" ROI delta QP: %d", roi_config->bits.num_roi_regions,
|
2017-08-17 10:44:40 +00:00
|
|
|
VA_ROI_RC_QP_DELTA_SUPPORT (roi_config));
|
2017-02-23 08:57:07 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
attrib->value = value;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-08 16:52:37 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
2017-02-23 08:57:07 +00:00
|
|
|
}
|
2017-08-09 20:45:40 +00:00
|
|
|
#endif
|
|
|
|
#if USE_H264_FEI_ENCODER
|
|
|
|
if (cip->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_FEI) {
|
|
|
|
attrib->type = (VAConfigAttribType) VAConfigAttribFEIFunctionType;
|
2017-09-13 06:44:32 +00:00
|
|
|
attrib = &attribs[++attrib_index];
|
2017-08-09 20:45:40 +00:00
|
|
|
g_assert (attrib_index < G_N_ELEMENTS (attribs));
|
|
|
|
/* FIXME: Query the read-only supported MV predictors */
|
|
|
|
}
|
2015-02-04 09:17:58 +00:00
|
|
|
#endif
|
2014-01-23 12:30:41 +00:00
|
|
|
break;
|
2013-07-12 14:07:59 +00:00
|
|
|
}
|
2014-01-23 21:44:09 +00:00
|
|
|
#endif
|
2014-01-23 12:30:41 +00:00
|
|
|
default:
|
|
|
|
break;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_VAAPI_DISPLAY_LOCK (display);
|
|
|
|
status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (display),
|
2017-08-08 16:52:37 +00:00
|
|
|
context->va_profile, context->va_entrypoint, attribs, attrib_index,
|
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, "vaCreateConfig()"))
|
2014-01-23 08:41:07 +00:00
|
|
|
goto cleanup;
|
2014-01-23 08:27:38 +00:00
|
|
|
|
2016-12-02 00:28:07 +00:00
|
|
|
return TRUE;
|
2014-01-23 08:41:07 +00:00
|
|
|
cleanup:
|
2016-12-02 00:28:07 +00:00
|
|
|
GST_WARNING ("Failed to create vaConfig");
|
|
|
|
return FALSE;
|
2010-04-23 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 13:01:33 +00:00
|
|
|
/** Updates config for encoding. Returns %TRUE if config changed */
|
|
|
|
static gboolean
|
|
|
|
context_update_config_encoder (GstVaapiContext * context,
|
|
|
|
const GstVaapiConfigInfoEncoder * new_config)
|
|
|
|
{
|
|
|
|
GstVaapiConfigInfoEncoder *const config = &context->info.config.encoder;
|
|
|
|
gboolean config_changed = FALSE;
|
|
|
|
|
|
|
|
g_assert (context->info.usage == GST_VAAPI_CONTEXT_USAGE_ENCODE);
|
|
|
|
|
|
|
|
if (config->rc_mode != new_config->rc_mode) {
|
|
|
|
config->rc_mode = new_config->rc_mode;
|
|
|
|
config_changed = TRUE;
|
|
|
|
}
|
2014-01-23 14:13:06 +00:00
|
|
|
|
|
|
|
if (config->packed_headers != new_config->packed_headers) {
|
|
|
|
config->packed_headers = new_config->packed_headers;
|
|
|
|
config_changed = TRUE;
|
|
|
|
}
|
2017-02-23 08:57:07 +00:00
|
|
|
|
|
|
|
if (config->roi_capability != new_config->roi_capability ||
|
|
|
|
config->roi_num_supported != new_config->roi_num_supported) {
|
|
|
|
config->roi_capability = new_config->roi_capability;
|
|
|
|
config->roi_num_supported = new_config->roi_num_supported;
|
|
|
|
config_changed = TRUE;
|
|
|
|
}
|
|
|
|
|
2014-01-23 13:01:33 +00:00
|
|
|
return config_changed;
|
|
|
|
}
|
|
|
|
|
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,
|
2014-04-25 11:45:31 +00:00
|
|
|
const GstVaapiContextInfo * new_cip)
|
2010-04-23 15:59:31 +00:00
|
|
|
{
|
2014-04-25 11:45:31 +00:00
|
|
|
GstVaapiContextInfo *const cip = &context->info;
|
|
|
|
|
|
|
|
*cip = *new_cip;
|
|
|
|
if (!cip->chroma_type)
|
|
|
|
cip->chroma_type = DEFAULT_CHROMA_TYPE;
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
context->va_config = VA_INVALID_ID;
|
2016-05-17 22:34:23 +00:00
|
|
|
context->reset_on_resize = TRUE;
|
2014-01-23 09:59:20 +00:00
|
|
|
gst_vaapi_context_overlay_init (context);
|
2016-02-18 18:32:58 +00:00
|
|
|
|
|
|
|
context->formats = NULL;
|
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:41:07 +00:00
|
|
|
context_destroy (context);
|
|
|
|
context_destroy_surfaces (context);
|
2014-01-23 09:59:20 +00:00
|
|
|
gst_vaapi_context_overlay_finalize (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);
|
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);
|
2016-12-02 00:28:07 +00:00
|
|
|
|
|
|
|
if (!config_create (context))
|
|
|
|
goto error;
|
|
|
|
|
2016-12-02 00:30:52 +00:00
|
|
|
/* this means we don't want to create a VAcontext */
|
|
|
|
if (cip->width == 0 && cip->height == 0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/* this is not valid */
|
|
|
|
if (cip->width == 0 || cip->height == 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-01-23 08:41:07 +00:00
|
|
|
if (!context_create (context))
|
2014-01-23 08:27:38 +00:00
|
|
|
goto error;
|
2016-12-02 00:30:52 +00:00
|
|
|
|
|
|
|
done:
|
2014-01-23 08:27:38 +00:00
|
|
|
return context;
|
2013-04-30 15:22:15 +00:00
|
|
|
|
2016-10-19 17:04:20 +00:00
|
|
|
/* ERRORS */
|
2013-04-30 15:22:15 +00:00
|
|
|
error:
|
2016-10-19 17:04:20 +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-04-25 11:45:31 +00:00
|
|
|
gboolean reset_surfaces = FALSE, reset_config = FALSE;
|
2014-05-03 13:56:51 +00:00
|
|
|
gboolean grow_surfaces = FALSE;
|
2014-04-25 11:45:31 +00:00
|
|
|
GstVaapiChromaType chroma_type;
|
|
|
|
|
|
|
|
chroma_type = new_cip->chroma_type ? new_cip->chroma_type :
|
|
|
|
DEFAULT_CHROMA_TYPE;
|
|
|
|
if (cip->chroma_type != chroma_type) {
|
|
|
|
cip->chroma_type = chroma_type;
|
|
|
|
reset_surfaces = TRUE;
|
|
|
|
}
|
2014-01-23 08:27:38 +00:00
|
|
|
|
2014-04-25 11:45:31 +00:00
|
|
|
if (cip->width != new_cip->width || cip->height != new_cip->height) {
|
2014-01-23 08:27:38 +00:00
|
|
|
cip->width = new_cip->width;
|
|
|
|
cip->height = new_cip->height;
|
2014-04-25 11:45:31 +00:00
|
|
|
reset_surfaces = TRUE;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
|
|
|
|
2014-04-25 11:45:31 +00:00
|
|
|
if (cip->profile != new_cip->profile ||
|
|
|
|
cip->entrypoint != new_cip->entrypoint) {
|
2014-01-23 08:27:38 +00:00
|
|
|
cip->profile = new_cip->profile;
|
|
|
|
cip->entrypoint = new_cip->entrypoint;
|
2014-04-25 11:45:31 +00:00
|
|
|
reset_config = TRUE;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
|
|
|
|
2014-05-03 13:56:51 +00:00
|
|
|
if (cip->ref_frames < new_cip->ref_frames) {
|
|
|
|
cip->ref_frames = new_cip->ref_frames;
|
|
|
|
grow_surfaces = TRUE;
|
|
|
|
}
|
|
|
|
|
2014-01-23 12:30:41 +00:00
|
|
|
if (cip->usage != new_cip->usage) {
|
|
|
|
cip->usage = new_cip->usage;
|
2014-04-25 11:45:31 +00:00
|
|
|
reset_config = TRUE;
|
2014-01-23 13:01:33 +00:00
|
|
|
memcpy (&cip->config, &new_cip->config, sizeof (cip->config));
|
2014-01-23 12:30:41 +00:00
|
|
|
} else if (new_cip->usage == GST_VAAPI_CONTEXT_USAGE_ENCODE) {
|
2014-01-23 13:01:33 +00:00
|
|
|
if (context_update_config_encoder (context, &new_cip->config.encoder))
|
2014-04-25 11:45:31 +00:00
|
|
|
reset_config = TRUE;
|
2014-05-03 13:47:53 +00:00
|
|
|
} else if (new_cip->usage == GST_VAAPI_CONTEXT_USAGE_DECODE) {
|
2016-05-17 22:34:23 +00:00
|
|
|
if ((reset_surfaces && context->reset_on_resize) || grow_surfaces)
|
2014-05-03 13:47:53 +00:00
|
|
|
reset_config = TRUE;
|
2014-01-23 08:27:38 +00:00
|
|
|
}
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-04-25 11:45:31 +00:00
|
|
|
if (reset_surfaces)
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy_surfaces (context);
|
2014-04-25 11:45:31 +00:00
|
|
|
if (reset_config)
|
2014-01-23 08:41:07 +00:00
|
|
|
context_destroy (context);
|
2010-04-23 15:59:31 +00:00
|
|
|
|
2014-04-25 11:45:31 +00:00
|
|
|
if (reset_surfaces && !context_create_surfaces (context))
|
2014-01-23 08:41:07 +00:00
|
|
|
return FALSE;
|
2014-05-03 13:56:51 +00:00
|
|
|
else if (grow_surfaces && !context_ensure_surfaces (context))
|
|
|
|
return FALSE;
|
2016-12-02 00:28:07 +00:00
|
|
|
if (reset_config && !(config_create (context) && 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
|
|
|
}
|
2016-05-17 22:34:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_reset_on_resize:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
* @reset_on_resize: Should the context be reset on size change
|
|
|
|
*
|
|
|
|
* Sets whether the underlying context should be reset when a size change
|
|
|
|
* happens. The proper setting for this is codec dependent.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
gst_vaapi_context_reset_on_resize (GstVaapiContext * context,
|
|
|
|
gboolean reset_on_resize)
|
|
|
|
{
|
|
|
|
g_return_if_fail (context != NULL);
|
|
|
|
|
|
|
|
context->reset_on_resize = reset_on_resize;
|
|
|
|
}
|
2016-02-18 18:32:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_vaapi_context_get_surface_formats:
|
|
|
|
* @context: a #GstVaapiContext
|
|
|
|
*
|
|
|
|
* Determines the set of supported formats by the surfaces associated
|
|
|
|
* to @context. The caller owns an extra reference of the resulting
|
|
|
|
* array of #GstVideoFormat elements, so it shall be released with
|
|
|
|
* g_array_unref after usage.
|
|
|
|
*
|
|
|
|
* Return value: (transfer full): the set of target formats supported
|
|
|
|
* by the surfaces in @context.
|
|
|
|
*/
|
|
|
|
GArray *
|
|
|
|
gst_vaapi_context_get_surface_formats (GstVaapiContext * context)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (context, NULL);
|
|
|
|
|
|
|
|
if (!ensure_formats (context))
|
|
|
|
return NULL;
|
|
|
|
return g_array_ref (context->formats);
|
|
|
|
}
|