mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
Add initial infrastructure for video processing.
Add initial API for video processing: only scaling and color format conversion operations are supported.
This commit is contained in:
parent
f34b6ffc60
commit
f09008a8d1
8 changed files with 995 additions and 0 deletions
29
configure.ac
29
configure.ac
|
@ -615,6 +615,31 @@ AC_CACHE_CHECK([for JPEG decoding API],
|
||||||
LIBS="$saved_LIBS"
|
LIBS="$saved_LIBS"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl Check for vpp (video post-processing) support
|
||||||
|
USE_VA_VPP=0
|
||||||
|
AC_CACHE_CHECK([for video post-postprocessing API],
|
||||||
|
ac_cv_have_va_vpp_api, [
|
||||||
|
saved_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS $LIBVA_CFLAGS"
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $LIBVA_LIBS"
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[[#include <va/va.h>
|
||||||
|
#include <va/va_vpp.h>]],
|
||||||
|
[[VADisplay va_dpy;
|
||||||
|
VAContextID vpp_ctx;
|
||||||
|
VAProcFilterType filters[VAProcFilterCount];
|
||||||
|
unsigned int num_filters = VAProcFilterCount;
|
||||||
|
vaQueryVideoProcFilters(va_dpy, vpp_ctx, filters, &num_filters);
|
||||||
|
]])],
|
||||||
|
[ac_cv_have_va_vpp_api="yes" USE_VA_VPP=1],
|
||||||
|
[ac_cv_have_va_vpp_api="no"]
|
||||||
|
)
|
||||||
|
CPPFLAGS="$saved_CPPFLAGS"
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
])
|
||||||
|
|
||||||
dnl VA/Wayland API
|
dnl VA/Wayland API
|
||||||
if test "$enable_wayland" = "yes"; then
|
if test "$enable_wayland" = "yes"; then
|
||||||
PKG_CHECK_MODULES([LIBVA_WAYLAND], [libva-wayland >= va_api_wld_version],
|
PKG_CHECK_MODULES([LIBVA_WAYLAND], [libva-wayland >= va_api_wld_version],
|
||||||
|
@ -633,6 +658,10 @@ case ":$USE_X11:$USE_GLX:$USE_WAYLAND:$USE_DRM:" in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED(USE_VA_VPP, $USE_VA_VPP,
|
||||||
|
[Defined to 1 if video post-processing is used])
|
||||||
|
AM_CONDITIONAL(USE_VA_VPP, test $USE_VA_VPP -eq 1)
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(USE_JPEG_DECODER, $USE_JPEG_DECODER,
|
AC_DEFINE_UNQUOTED(USE_JPEG_DECODER, $USE_JPEG_DECODER,
|
||||||
[Defined to 1 if JPEG decoder is used])
|
[Defined to 1 if JPEG decoder is used])
|
||||||
AM_CONDITIONAL(USE_JPEG_DECODER, test $USE_JPEG_DECODER -eq 1)
|
AM_CONDITIONAL(USE_JPEG_DECODER, test $USE_JPEG_DECODER -eq 1)
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<xi:include href="xml/gstvaapidecoder_h264.xml"/>
|
<xi:include href="xml/gstvaapidecoder_h264.xml"/>
|
||||||
<xi:include href="xml/gstvaapidecoder_vc1.xml"/>
|
<xi:include href="xml/gstvaapidecoder_vc1.xml"/>
|
||||||
<xi:include href="xml/gstvaapisurfaceproxy.xml"/>
|
<xi:include href="xml/gstvaapisurfaceproxy.xml"/>
|
||||||
|
<xi:include href="xml/gstvaapifilter.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="object-tree">
|
<chapter id="object-tree">
|
||||||
|
|
|
@ -373,3 +373,19 @@ gst_vaapi_surface_proxy_unref
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GST_VAAPI_SURFACE_PROXY_SURFACE
|
GST_VAAPI_SURFACE_PROXY_SURFACE
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>gstvaapifilter</FILE>
|
||||||
|
<TITLE>GstVaapiFilter</TITLE>
|
||||||
|
GstVaapiFilter
|
||||||
|
gst_vaapi_filter_new
|
||||||
|
gst_vaapi_filter_ref
|
||||||
|
gst_vaapi_filter_unref
|
||||||
|
gst_vaapi_filter_replace
|
||||||
|
gst_vaapi_filter_get_operations
|
||||||
|
gst_vaapi_filter_get_formats
|
||||||
|
gst_vaapi_filter_set_operation
|
||||||
|
gst_vaapi_filter_set_format
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
GST_VAAPI_FILTER
|
||||||
|
</SECTION>
|
||||||
|
|
|
@ -55,6 +55,7 @@ libgstvaapi_source_c = \
|
||||||
gstvaapidecoder_vc1.c \
|
gstvaapidecoder_vc1.c \
|
||||||
gstvaapidisplay.c \
|
gstvaapidisplay.c \
|
||||||
gstvaapidisplaycache.c \
|
gstvaapidisplaycache.c \
|
||||||
|
gstvaapifilter.c \
|
||||||
gstvaapiimage.c \
|
gstvaapiimage.c \
|
||||||
gstvaapiimagepool.c \
|
gstvaapiimagepool.c \
|
||||||
gstvaapiminiobject.c \
|
gstvaapiminiobject.c \
|
||||||
|
|
|
@ -684,6 +684,18 @@ gst_vaapi_display_create(GstVaapiDisplay *display,
|
||||||
}
|
}
|
||||||
append_h263_config(priv->decoders);
|
append_h263_config(priv->decoders);
|
||||||
|
|
||||||
|
/* Video processing API */
|
||||||
|
#if USE_VA_VPP
|
||||||
|
status = vaQueryConfigEntrypoints(priv->display, VAProfileNone,
|
||||||
|
entrypoints, &num_entrypoints);
|
||||||
|
if (vaapi_check_status(status, "vaQueryEntrypoints() [VAProfileNone]")) {
|
||||||
|
for (j = 0; j < num_entrypoints; j++) {
|
||||||
|
if (entrypoints[j] == VAEntrypointVideoProc)
|
||||||
|
priv->has_vpp = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* VA display attributes */
|
/* VA display attributes */
|
||||||
display_attrs =
|
display_attrs =
|
||||||
g_new(VADisplayAttribute, vaMaxNumDisplayAttributes(priv->display));
|
g_new(VADisplayAttribute, vaMaxNumDisplayAttributes(priv->display));
|
||||||
|
|
|
@ -116,6 +116,16 @@ typedef void (*GstVaapiDisplayGetSizeMFunc)(GstVaapiDisplay *display,
|
||||||
#define GST_VAAPI_DISPLAY_TYPES(display) \
|
#define GST_VAAPI_DISPLAY_TYPES(display) \
|
||||||
gst_vaapi_display_get_display_types(GST_VAAPI_DISPLAY_CAST(display))
|
gst_vaapi_display_get_display_types(GST_VAAPI_DISPLAY_CAST(display))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_VAAPI_DISPLAY_HAS_VPP:
|
||||||
|
* @display: a @GstVaapiDisplay
|
||||||
|
*
|
||||||
|
* Returns whether the @display supports video processing (VA/VPP)
|
||||||
|
*/
|
||||||
|
#undef GST_VAAPI_DISPLAY_HAS_VPP
|
||||||
|
#define GST_VAAPI_DISPLAY_HAS_VPP(display) \
|
||||||
|
(GST_VAAPI_DISPLAY_GET_PRIVATE(display)->has_vpp)
|
||||||
|
|
||||||
struct _GstVaapiDisplayPrivate {
|
struct _GstVaapiDisplayPrivate {
|
||||||
GstVaapiDisplay *parent;
|
GstVaapiDisplay *parent;
|
||||||
GRecMutex mutex;
|
GRecMutex mutex;
|
||||||
|
@ -133,6 +143,7 @@ struct _GstVaapiDisplayPrivate {
|
||||||
GArray *subpicture_formats;
|
GArray *subpicture_formats;
|
||||||
GArray *properties;
|
GArray *properties;
|
||||||
guint use_foreign_display : 1;
|
guint use_foreign_display : 1;
|
||||||
|
guint has_vpp : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
821
gst-libs/gst/vaapi/gstvaapifilter.c
Normal file
821
gst-libs/gst/vaapi/gstvaapifilter.c
Normal file
|
@ -0,0 +1,821 @@
|
||||||
|
/*
|
||||||
|
* gstvaapifilter.c - Video processing abstraction
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Intel Corporation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
#include "gstvaapifilter.h"
|
||||||
|
#include "gstvaapiutils.h"
|
||||||
|
#include "gstvaapiminiobject.h"
|
||||||
|
#include "gstvaapidisplay_priv.h"
|
||||||
|
#include "gstvaapisurface_priv.h"
|
||||||
|
|
||||||
|
#if USE_VA_VPP
|
||||||
|
# include <va/va_vpp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
#include "gstvaapidebug.h"
|
||||||
|
|
||||||
|
#define GST_VAAPI_FILTER(obj) \
|
||||||
|
((GstVaapiFilter *)(obj))
|
||||||
|
|
||||||
|
typedef struct _GstVaapiFilterOpData GstVaapiFilterOpData;
|
||||||
|
struct _GstVaapiFilterOpData {
|
||||||
|
GstVaapiFilterOp op;
|
||||||
|
GParamSpec *pspec;
|
||||||
|
volatile gint ref_count;
|
||||||
|
guint va_type;
|
||||||
|
guint va_subtype;
|
||||||
|
gpointer va_caps;
|
||||||
|
guint va_num_caps;
|
||||||
|
guint va_cap_size;
|
||||||
|
VABufferID va_buffer;
|
||||||
|
guint va_buffer_size;
|
||||||
|
guint is_enabled : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVaapiFilter {
|
||||||
|
/*< private >*/
|
||||||
|
GstVaapiMiniObject parent_instance;
|
||||||
|
|
||||||
|
GstVaapiDisplay *display;
|
||||||
|
VADisplay va_display;
|
||||||
|
VAConfigID va_config;
|
||||||
|
VAContextID va_context;
|
||||||
|
GPtrArray *operations;
|
||||||
|
GstVideoFormat format;
|
||||||
|
GArray *formats;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- VPP Helpers --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if USE_VA_VPP
|
||||||
|
static VAProcFilterType *
|
||||||
|
vpp_get_filters_unlocked(GstVaapiFilter *filter, guint *num_filters_ptr)
|
||||||
|
{
|
||||||
|
VAProcFilterType *filters = NULL;
|
||||||
|
guint num_filters = 0;
|
||||||
|
VAStatus va_status;
|
||||||
|
|
||||||
|
num_filters = VAProcFilterCount;
|
||||||
|
filters = g_malloc_n(num_filters, sizeof(*filters));
|
||||||
|
if (!filters)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
va_status = vaQueryVideoProcFilters(filter->va_display, filter->va_context,
|
||||||
|
filters, &num_filters);
|
||||||
|
|
||||||
|
// Try to reallocate to the expected number of filters
|
||||||
|
if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
|
||||||
|
VAProcFilterType * const new_filters =
|
||||||
|
g_try_realloc_n(filters, num_filters, sizeof(*new_filters));
|
||||||
|
if (!new_filters)
|
||||||
|
goto error;
|
||||||
|
filters = new_filters;
|
||||||
|
|
||||||
|
va_status = vaQueryVideoProcFilters(filter->va_display,
|
||||||
|
filter->va_context, filters, &num_filters);
|
||||||
|
}
|
||||||
|
if (!vaapi_check_status(va_status, "vaQueryVideoProcFilters()"))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
*num_filters_ptr = num_filters;
|
||||||
|
return filters;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free(filters);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VAProcFilterType *
|
||||||
|
vpp_get_filters(GstVaapiFilter *filter, guint *num_filters_ptr)
|
||||||
|
{
|
||||||
|
VAProcFilterType *filters;
|
||||||
|
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(filter->display);
|
||||||
|
filters = vpp_get_filters_unlocked(filter, num_filters_ptr);
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- VPP Operations --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if USE_VA_VPP
|
||||||
|
#define DEFAULT_FORMAT GST_VIDEO_FORMAT_UNKNOWN
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_FORMAT = GST_VAAPI_FILTER_OP_FORMAT,
|
||||||
|
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *g_properties[N_PROPERTIES] = { NULL, };
|
||||||
|
static gsize g_properties_initialized = FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_properties(void)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* GstVaapiFilter:format:
|
||||||
|
*
|
||||||
|
* The forced output pixel format, expressed as a #GstVideoFormat.
|
||||||
|
*/
|
||||||
|
g_properties[PROP_FORMAT] =
|
||||||
|
g_param_spec_enum("format",
|
||||||
|
"Format",
|
||||||
|
"The forced output pixel format",
|
||||||
|
GST_TYPE_VIDEO_FORMAT,
|
||||||
|
DEFAULT_FORMAT,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_properties(void)
|
||||||
|
{
|
||||||
|
if (g_once_init_enter(&g_properties_initialized)) {
|
||||||
|
init_properties();
|
||||||
|
g_once_init_leave(&g_properties_initialized, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
op_data_free(GstVaapiFilterOpData *op_data)
|
||||||
|
{
|
||||||
|
g_free(op_data->va_caps);
|
||||||
|
g_slice_free(GstVaapiFilterOpData, op_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gpointer
|
||||||
|
op_data_new(GstVaapiFilterOp op, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GstVaapiFilterOpData *op_data;
|
||||||
|
|
||||||
|
op_data = g_slice_new0(GstVaapiFilterOpData);
|
||||||
|
if (!op_data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
op_data->op = op;
|
||||||
|
op_data->pspec = pspec;
|
||||||
|
op_data->ref_count = 1;
|
||||||
|
op_data->va_buffer = VA_INVALID_ID;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case GST_VAAPI_FILTER_OP_FORMAT:
|
||||||
|
op_data->va_type = VAProcFilterNone;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert(0 && "unsupported operation");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
return op_data;
|
||||||
|
|
||||||
|
error:
|
||||||
|
op_data_free(op_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gpointer
|
||||||
|
op_data_ref(gpointer data)
|
||||||
|
{
|
||||||
|
GstVaapiFilterOpData * const op_data = data;
|
||||||
|
|
||||||
|
g_return_val_if_fail(op_data != NULL, NULL);
|
||||||
|
|
||||||
|
g_atomic_int_inc(&op_data->ref_count);
|
||||||
|
return op_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
op_data_unref(gpointer data)
|
||||||
|
{
|
||||||
|
GstVaapiFilterOpData * const op_data = data;
|
||||||
|
|
||||||
|
g_return_if_fail(op_data != NULL);
|
||||||
|
g_return_if_fail(op_data->ref_count > 0);
|
||||||
|
|
||||||
|
if (g_atomic_int_dec_and_test(&op_data->ref_count))
|
||||||
|
op_data_free(op_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get default list of operations supported by the library */
|
||||||
|
static GPtrArray *
|
||||||
|
get_operations_default(void)
|
||||||
|
{
|
||||||
|
GPtrArray *ops;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
ops = g_ptr_array_new_full(N_PROPERTIES, op_data_unref);
|
||||||
|
if (!ops)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ensure_properties();
|
||||||
|
|
||||||
|
for (i = 0; i < N_PROPERTIES; i++) {
|
||||||
|
GParamSpec * const pspec = g_properties[i];
|
||||||
|
if (!pspec)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
GstVaapiFilterOpData * const op_data = op_data_new(i, pspec);
|
||||||
|
if (!op_data)
|
||||||
|
goto error;
|
||||||
|
g_ptr_array_add(ops, op_data);
|
||||||
|
}
|
||||||
|
return ops;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_ptr_array_unref(ops);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the ordered list of operations, based on VA/VPP queries */
|
||||||
|
static GPtrArray *
|
||||||
|
get_operations_ordered(GstVaapiFilter *filter, GPtrArray *default_ops)
|
||||||
|
{
|
||||||
|
GPtrArray *ops;
|
||||||
|
VAProcFilterType *filters;
|
||||||
|
guint i, j, num_filters;
|
||||||
|
|
||||||
|
ops = g_ptr_array_new_full(default_ops->len, op_data_unref);
|
||||||
|
if (!ops)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
filters = vpp_get_filters(filter, &num_filters);
|
||||||
|
if (!filters)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
// Append virtual ops first, i.e. those without an associated VA filter
|
||||||
|
for (i = 0; i < default_ops->len; i++) {
|
||||||
|
GstVaapiFilterOpData * const op_data =
|
||||||
|
g_ptr_array_index(default_ops, i);
|
||||||
|
if (op_data->va_type == VAProcFilterNone)
|
||||||
|
g_ptr_array_add(ops, op_data_ref(op_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append ops, while preserving the VA filters ordering
|
||||||
|
for (i = 0; i < num_filters; i++) {
|
||||||
|
const VAProcFilterType va_type = filters[i];
|
||||||
|
if (va_type == VAProcFilterNone)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (j = 0; j < default_ops->len; j++) {
|
||||||
|
GstVaapiFilterOpData * const op_data =
|
||||||
|
g_ptr_array_index(default_ops, j);
|
||||||
|
if (op_data->va_type != va_type)
|
||||||
|
continue;
|
||||||
|
g_ptr_array_add(ops, op_data_ref(op_data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter->operations)
|
||||||
|
g_ptr_array_unref(filter->operations);
|
||||||
|
filter->operations = g_ptr_array_ref(ops);
|
||||||
|
|
||||||
|
g_free(filters);
|
||||||
|
g_ptr_array_unref(default_ops);
|
||||||
|
return ops;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free(filters);
|
||||||
|
g_ptr_array_unref(ops);
|
||||||
|
g_ptr_array_unref(default_ops);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the set of supported VPP operations by the specific
|
||||||
|
filter, or known to this library if filter is NULL */
|
||||||
|
static GPtrArray *
|
||||||
|
ensure_operations(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
GPtrArray *ops;
|
||||||
|
|
||||||
|
if (filter && filter->operations)
|
||||||
|
return g_ptr_array_ref(filter->operations);
|
||||||
|
|
||||||
|
ops = get_operations_default();
|
||||||
|
if (!ops)
|
||||||
|
return NULL;
|
||||||
|
return filter ? get_operations_ordered(filter, ops) : ops;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Find whether the VPP operation is supported or not */
|
||||||
|
GstVaapiFilterOpData *
|
||||||
|
find_operation(GstVaapiFilter *filter, GstVaapiFilterOp op)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (!filter->operations)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < filter->operations->len; i++) {
|
||||||
|
GstVaapiFilterOpData * const op_data =
|
||||||
|
g_ptr_array_index(filter->operations, i);
|
||||||
|
if (op_data->op == op)
|
||||||
|
return op_data;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- Surface Formats --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static GArray *
|
||||||
|
ensure_formats(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
VASurfaceAttrib *surface_attribs = NULL;
|
||||||
|
guint i, num_surface_attribs = 0;
|
||||||
|
VAStatus va_status;
|
||||||
|
|
||||||
|
if (G_LIKELY(filter->formats))
|
||||||
|
return filter->formats;
|
||||||
|
|
||||||
|
#if VA_CHECK_VERSION(0,34,0)
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(filter->display);
|
||||||
|
va_status = vaQuerySurfaceAttributes(filter->va_display, filter->va_config,
|
||||||
|
NULL, &num_surface_attribs);
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
|
||||||
|
if (!vaapi_check_status(va_status, "vaQuerySurfaceAttributes()"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
surface_attribs = g_malloc(num_surface_attribs * sizeof(*surface_attribs));
|
||||||
|
if (!surface_attribs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(filter->display);
|
||||||
|
va_status = vaQuerySurfaceAttributes(filter->va_display, filter->va_config,
|
||||||
|
surface_attribs, &num_surface_attribs);
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
|
||||||
|
if (!vaapi_check_status(va_status, "vaQuerySurfaceAttributes()"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
filter->formats = g_array_sized_new(FALSE, FALSE, sizeof(GstVideoFormat),
|
||||||
|
num_surface_attribs);
|
||||||
|
if (!filter->formats)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for (i = 0; i < num_surface_attribs; i++) {
|
||||||
|
const VASurfaceAttrib * const surface_attrib = &surface_attribs[i];
|
||||||
|
GstVideoFormat format;
|
||||||
|
|
||||||
|
if (surface_attrib->type != VASurfaceAttribPixelFormat)
|
||||||
|
continue;
|
||||||
|
if (!(surface_attrib->flags & VA_SURFACE_ATTRIB_SETTABLE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
format = gst_vaapi_video_format_from_va_fourcc(
|
||||||
|
surface_attrib->value.value.i);
|
||||||
|
if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
g_array_append_val(filter->formats, format);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_free(surface_attribs);
|
||||||
|
return filter->formats;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free(surface_attribs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
is_special_format(GstVideoFormat format)
|
||||||
|
{
|
||||||
|
return format == GST_VIDEO_FORMAT_UNKNOWN ||
|
||||||
|
format == GST_VIDEO_FORMAT_ENCODED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find_format(GstVaapiFilter *filter, GstVideoFormat format)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (is_special_format(format) || !filter->formats)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < filter->formats->len; i++) {
|
||||||
|
if (g_array_index(filter->formats, GstVideoFormat, i) == format)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
/* --- Interface --- */
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if USE_VA_VPP
|
||||||
|
static gboolean
|
||||||
|
gst_vaapi_filter_init(GstVaapiFilter *filter, GstVaapiDisplay *display)
|
||||||
|
{
|
||||||
|
VAStatus va_status;
|
||||||
|
|
||||||
|
filter->display = gst_vaapi_display_ref(display);
|
||||||
|
filter->va_display = GST_VAAPI_DISPLAY_VADISPLAY(display);
|
||||||
|
filter->va_config = VA_INVALID_ID;
|
||||||
|
filter->va_context = VA_INVALID_ID;
|
||||||
|
filter->format = DEFAULT_FORMAT;
|
||||||
|
|
||||||
|
if (!GST_VAAPI_DISPLAY_HAS_VPP(display))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
va_status = vaCreateConfig(filter->va_display, VAProfileNone,
|
||||||
|
VAEntrypointVideoProc, NULL, 0, &filter->va_config);
|
||||||
|
if (!vaapi_check_status(va_status, "vaCreateConfig() [VPP]"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
va_status = vaCreateContext(filter->va_display, filter->va_config, 0, 0, 0,
|
||||||
|
NULL, 0, &filter->va_context);
|
||||||
|
if (!vaapi_check_status(va_status, "vaCreateContext() [VPP]"))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_vaapi_filter_finalize(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(filter->display);
|
||||||
|
if (filter->operations) {
|
||||||
|
for (i = 0; i < filter->operations->len; i++) {
|
||||||
|
GstVaapiFilterOpData * const op_data =
|
||||||
|
g_ptr_array_index(filter->operations, i);
|
||||||
|
vaapi_destroy_buffer(filter->va_display, &op_data->va_buffer);
|
||||||
|
}
|
||||||
|
g_ptr_array_unref(filter->operations);
|
||||||
|
filter->operations = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter->va_context != VA_INVALID_ID) {
|
||||||
|
vaDestroyContext(filter->va_display, filter->va_context);
|
||||||
|
filter->va_context = VA_INVALID_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter->va_config != VA_INVALID_ID) {
|
||||||
|
vaDestroyConfig(filter->va_display, filter->va_config);
|
||||||
|
filter->va_config = VA_INVALID_ID;
|
||||||
|
}
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
|
||||||
|
gst_vaapi_display_replace(&filter->display, NULL);
|
||||||
|
|
||||||
|
if (filter->formats) {
|
||||||
|
g_array_unref(filter->formats);
|
||||||
|
filter->formats = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const GstVaapiMiniObjectClass *
|
||||||
|
gst_vaapi_filter_class(void)
|
||||||
|
{
|
||||||
|
static const GstVaapiMiniObjectClass GstVaapiFilterClass = {
|
||||||
|
sizeof(GstVaapiFilter),
|
||||||
|
(GDestroyNotify)gst_vaapi_filter_finalize
|
||||||
|
};
|
||||||
|
return &GstVaapiFilterClass;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_new:
|
||||||
|
* @display: a #GstVaapiDisplay
|
||||||
|
*
|
||||||
|
* Creates a new #GstVaapiFilter set up to operate in "identity"
|
||||||
|
* mode. This means that no other operation than scaling is performed.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #GstVaapiFilter object
|
||||||
|
*/
|
||||||
|
GstVaapiFilter *
|
||||||
|
gst_vaapi_filter_new(GstVaapiDisplay *display)
|
||||||
|
{
|
||||||
|
#if USE_VA_VPP
|
||||||
|
GstVaapiFilter *filter;
|
||||||
|
|
||||||
|
filter = (GstVaapiFilter *)
|
||||||
|
gst_vaapi_mini_object_new0(gst_vaapi_filter_class());
|
||||||
|
if (!filter)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!gst_vaapi_filter_init(filter, display))
|
||||||
|
goto error;
|
||||||
|
return filter;
|
||||||
|
|
||||||
|
error:
|
||||||
|
gst_vaapi_filter_unref(filter);
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
GST_WARNING("video processing is not supported, "
|
||||||
|
"please consider an upgrade to VA-API >= 0.34");
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_ref:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
*
|
||||||
|
* Atomically increases the reference count of the given @filter by one.
|
||||||
|
*
|
||||||
|
* Returns: The same @filter argument
|
||||||
|
*/
|
||||||
|
GstVaapiFilter *
|
||||||
|
gst_vaapi_filter_ref(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail(filter != NULL, NULL);
|
||||||
|
|
||||||
|
return GST_VAAPI_FILTER(gst_vaapi_mini_object_ref(
|
||||||
|
GST_VAAPI_MINI_OBJECT(filter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_unref:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
*
|
||||||
|
* Atomically decreases the reference count of the @filter by one. If
|
||||||
|
* the reference count reaches zero, the filter will be free'd.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_vaapi_filter_unref(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
g_return_if_fail(filter != NULL);
|
||||||
|
|
||||||
|
gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_replace:
|
||||||
|
* @old_filter_ptr: a pointer to a #GstVaapiFilter
|
||||||
|
* @new_filter: a #GstVaapiFilter
|
||||||
|
*
|
||||||
|
* Atomically replaces the filter held in @old_filter_ptr with
|
||||||
|
* @new_filter. This means that @old_filter_ptr shall reference a
|
||||||
|
* valid filter. However, @new_filter can be NULL.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_vaapi_filter_replace(GstVaapiFilter **old_filter_ptr,
|
||||||
|
GstVaapiFilter *new_filter)
|
||||||
|
{
|
||||||
|
g_return_if_fail(old_filter_ptr != NULL);
|
||||||
|
|
||||||
|
gst_vaapi_mini_object_replace((GstVaapiMiniObject **)old_filter_ptr,
|
||||||
|
GST_VAAPI_MINI_OBJECT(new_filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_get_operations:
|
||||||
|
* @filter: a #GstVaapiFilter, or %NULL
|
||||||
|
*
|
||||||
|
* Determines the set of supported operations for video processing.
|
||||||
|
* The caller owns an extra reference to the resulting array of
|
||||||
|
* #GstVaapiFilterOpInfo elements, so it shall be released with
|
||||||
|
* g_ptr_array_unref() after usage.
|
||||||
|
*
|
||||||
|
* If @filter is %NULL, then this function returns the video
|
||||||
|
* processing operations supported by this library.
|
||||||
|
*
|
||||||
|
* Return value: the set of supported operations, or %NULL if an error
|
||||||
|
* occurred.
|
||||||
|
*/
|
||||||
|
GPtrArray *
|
||||||
|
gst_vaapi_filter_get_operations(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
#if USE_VA_VPP
|
||||||
|
return ensure_operations(filter);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_set_operation:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
* @op: a #GstVaapiFilterOp
|
||||||
|
* @value: the @op settings
|
||||||
|
*
|
||||||
|
* Enable the specified operation @op to be performed during video
|
||||||
|
* processing, i.e. in gst_vaapi_filter_process(). The @value argument
|
||||||
|
* specifies the operation settings. e.g. deinterlacing method for
|
||||||
|
* deinterlacing, denoising level for noise reduction, etc.
|
||||||
|
*
|
||||||
|
* If @value is %NULL, then this function resets the operation
|
||||||
|
* settings to their default values.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the specified operation may be supported,
|
||||||
|
* %FALSE otherwise
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_filter_set_operation(GstVaapiFilter *filter, GstVaapiFilterOp op,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
#if USE_VA_VPP
|
||||||
|
GstVaapiFilterOpData *op_data;
|
||||||
|
|
||||||
|
g_return_val_if_fail(filter != NULL, FALSE);
|
||||||
|
|
||||||
|
op_data = find_operation(filter, op);
|
||||||
|
if (!op_data)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (value && !G_VALUE_HOLDS(value, G_PARAM_SPEC_VALUE_TYPE(op_data->pspec)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case GST_VAAPI_FILTER_OP_FORMAT:
|
||||||
|
return gst_vaapi_filter_set_format(filter, value ?
|
||||||
|
g_value_get_enum(value) : DEFAULT_FORMAT);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_process:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
* @src_surface: the source @GstVaapiSurface
|
||||||
|
* @dst_surface: the destination @GstVaapiSurface
|
||||||
|
* @flags: #GstVaapiSurfaceRenderFlags that apply to @src_surface
|
||||||
|
*
|
||||||
|
* Applies the operations currently defined in the @filter to
|
||||||
|
* @src_surface and return the output in @dst_surface. The order of
|
||||||
|
* operations is determined in a way that suits best the underlying
|
||||||
|
* hardware. i.e. the only guarantee held is the generated outcome,
|
||||||
|
* not any specific order of operations.
|
||||||
|
*
|
||||||
|
* Return value: a #GstVaapiFilterStatus
|
||||||
|
*/
|
||||||
|
static GstVaapiFilterStatus
|
||||||
|
gst_vaapi_filter_process_unlocked(GstVaapiFilter *filter,
|
||||||
|
GstVaapiSurface *src_surface, GstVaapiSurface *dst_surface, guint flags)
|
||||||
|
{
|
||||||
|
#if USE_VA_VPP
|
||||||
|
VAProcPipelineParameterBuffer *pipeline_param = NULL;
|
||||||
|
VABufferID pipeline_param_buf_id;
|
||||||
|
VABufferID filters[N_PROPERTIES];
|
||||||
|
guint i, num_filters = 0;
|
||||||
|
VAStatus va_status;
|
||||||
|
VARectangle src_rect, dst_rect;
|
||||||
|
|
||||||
|
if (!ensure_operations(filter))
|
||||||
|
return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
|
|
||||||
|
src_rect.x = 0;
|
||||||
|
src_rect.y = 0;
|
||||||
|
src_rect.width = GST_VAAPI_SURFACE_WIDTH(src_surface);
|
||||||
|
src_rect.height = GST_VAAPI_SURFACE_HEIGHT(src_surface);
|
||||||
|
|
||||||
|
dst_rect.x = 0;
|
||||||
|
dst_rect.y = 0;
|
||||||
|
dst_rect.width = GST_VAAPI_SURFACE_WIDTH(dst_surface);
|
||||||
|
dst_rect.height = GST_VAAPI_SURFACE_HEIGHT(dst_surface);
|
||||||
|
|
||||||
|
for (i = 0, num_filters = 0; i < filter->operations->len; i++) {
|
||||||
|
GstVaapiFilterOpData * const op_data =
|
||||||
|
g_ptr_array_index(filter->operations, i);
|
||||||
|
if (!op_data->is_enabled)
|
||||||
|
continue;
|
||||||
|
if (op_data->va_buffer == VA_INVALID_ID) {
|
||||||
|
GST_ERROR("invalid VA buffer for operation %s",
|
||||||
|
g_param_spec_get_name(op_data->pspec));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
filters[num_filters++] = op_data->va_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vaapi_create_buffer(filter->va_display, filter->va_context,
|
||||||
|
VAProcPipelineParameterBufferType, sizeof(*pipeline_param),
|
||||||
|
NULL, &pipeline_param_buf_id, (gpointer *)&pipeline_param))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(pipeline_param, 0, sizeof(*pipeline_param));
|
||||||
|
pipeline_param->surface = GST_VAAPI_OBJECT_ID(src_surface);
|
||||||
|
pipeline_param->surface_region = &src_rect;
|
||||||
|
pipeline_param->surface_color_standard = VAProcColorStandardNone;
|
||||||
|
pipeline_param->output_region = &dst_rect;
|
||||||
|
pipeline_param->output_color_standard = VAProcColorStandardNone;
|
||||||
|
pipeline_param->output_background_color = 0xff000000;
|
||||||
|
pipeline_param->filter_flags = from_GstVaapiSurfaceRenderFlags(flags);
|
||||||
|
pipeline_param->filters = filters;
|
||||||
|
pipeline_param->num_filters = num_filters;
|
||||||
|
|
||||||
|
vaapi_unmap_buffer(filter->va_display, pipeline_param_buf_id, NULL);
|
||||||
|
|
||||||
|
va_status = vaBeginPicture(filter->va_display, filter->va_context,
|
||||||
|
GST_VAAPI_OBJECT_ID(dst_surface));
|
||||||
|
if (!vaapi_check_status(va_status, "vaBeginPicture()"))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
va_status = vaRenderPicture(filter->va_display, filter->va_context,
|
||||||
|
&pipeline_param_buf_id, 1);
|
||||||
|
if (!vaapi_check_status(va_status, "vaRenderPicture()"))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
va_status = vaEndPicture(filter->va_display, filter->va_context);
|
||||||
|
if (!vaapi_check_status(va_status, "vaEndPicture()"))
|
||||||
|
goto error;
|
||||||
|
return GST_VAAPI_FILTER_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
error:
|
||||||
|
vaDestroyBuffer(filter->va_display, pipeline_param_buf_id);
|
||||||
|
return GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED;
|
||||||
|
#endif
|
||||||
|
return GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstVaapiFilterStatus
|
||||||
|
gst_vaapi_filter_process(GstVaapiFilter *filter, GstVaapiSurface *src_surface,
|
||||||
|
GstVaapiSurface *dst_surface, guint flags)
|
||||||
|
{
|
||||||
|
GstVaapiFilterStatus status;
|
||||||
|
|
||||||
|
g_return_val_if_fail(filter != NULL,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
|
||||||
|
g_return_val_if_fail(src_surface != NULL,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
|
||||||
|
g_return_val_if_fail(dst_surface != NULL,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
GST_VAAPI_DISPLAY_LOCK(filter->display);
|
||||||
|
status = gst_vaapi_filter_process_unlocked(filter,
|
||||||
|
src_surface, dst_surface, flags);
|
||||||
|
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_get_formats:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
*
|
||||||
|
* Determines the set of supported source or target formats for video
|
||||||
|
* processing. The caller owns an extra reference to the resulting
|
||||||
|
* array of #GstVideoFormat elements, so it shall be released with
|
||||||
|
* g_array_unref() after usage.
|
||||||
|
*
|
||||||
|
* Return value: the set of supported target formats for video processing.
|
||||||
|
*/
|
||||||
|
GArray *
|
||||||
|
gst_vaapi_filter_get_formats(GstVaapiFilter *filter)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail(filter != NULL, NULL);
|
||||||
|
|
||||||
|
return ensure_formats(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_vaapi_filter_set_format:
|
||||||
|
* @filter: a #GstVaapiFilter
|
||||||
|
* @format: the target surface format
|
||||||
|
*
|
||||||
|
* Sets the desired pixel format of the resulting video processing
|
||||||
|
* operations.
|
||||||
|
*
|
||||||
|
* If @format is #GST_VIDEO_FORMAT_UNKNOWN, the filter will assume iso
|
||||||
|
* format conversion, i.e. no color conversion at all and the target
|
||||||
|
* surface format shall match the source surface format.
|
||||||
|
*
|
||||||
|
* If @format is #GST_VIDEO_FORMAT_ENCODED, the filter will use the pixel
|
||||||
|
* format of the target surface passed to gst_vaapi_filter_process().
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the color conversion to the specified @format
|
||||||
|
* may be supported, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_filter_set_format(GstVaapiFilter *filter, GstVideoFormat format)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail(filter != NULL, FALSE);
|
||||||
|
|
||||||
|
if (!ensure_formats(filter))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!is_special_format(format) && !find_format(filter, format))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
filter->format = format;
|
||||||
|
return TRUE;
|
||||||
|
}
|
104
gst-libs/gst/vaapi/gstvaapifilter.h
Normal file
104
gst-libs/gst/vaapi/gstvaapifilter.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* gstvaapifilter.h - Video processing abstraction
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Intel Corporation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GST_VAAPI_FILTER_H
|
||||||
|
#define GST_VAAPI_FILTER_H
|
||||||
|
|
||||||
|
#include <gst/vaapi/gstvaapisurface.h>
|
||||||
|
#include <gst/vaapi/video-format.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstVaapiFilter GstVaapiFilter;
|
||||||
|
typedef struct _GstVaapiFilterOpInfo GstVaapiFilterOpInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @GST_VAAPI_FILTER_OP_FORMAT: Force output pixel format (#GstVideoFormat).
|
||||||
|
*
|
||||||
|
* The set of operations that could be applied to the filter.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GST_VAAPI_FILTER_OP_FORMAT = 1,
|
||||||
|
} GstVaapiFilterOp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstVaapiFilterOpInfo:
|
||||||
|
* @operation: the #GstVaapiFilterOp
|
||||||
|
* @pspec: the #GParamSpec describing the associated configurable value
|
||||||
|
*
|
||||||
|
* A #GstVaapiFilterOp descriptor.
|
||||||
|
*/
|
||||||
|
struct _GstVaapiFilterOpInfo {
|
||||||
|
const GstVaapiFilterOp op;
|
||||||
|
GParamSpec * const pspec;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstVaapiFilterStatus:
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_SUCCESS: Success.
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED: No memory left.
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED: Operation failed.
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER: Invalid parameter.
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION: Unsupported operation.
|
||||||
|
* @GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT: Unsupported target format.
|
||||||
|
*
|
||||||
|
* Video processing status for gst_vaapi_filter_process().
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GST_VAAPI_FILTER_STATUS_SUCCESS = 0,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_OPERATION_FAILED,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_INVALID_PARAMETER,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_OPERATION,
|
||||||
|
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT,
|
||||||
|
} GstVaapiFilterStatus;
|
||||||
|
|
||||||
|
GstVaapiFilter *
|
||||||
|
gst_vaapi_filter_new(GstVaapiDisplay *display);
|
||||||
|
|
||||||
|
GstVaapiFilter *
|
||||||
|
gst_vaapi_filter_ref(GstVaapiFilter *filter);
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_vaapi_filter_unref(GstVaapiFilter *filter);
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_vaapi_filter_replace(GstVaapiFilter **old_filter_ptr,
|
||||||
|
GstVaapiFilter *new_filter);
|
||||||
|
|
||||||
|
GPtrArray *
|
||||||
|
gst_vaapi_filter_get_operations(GstVaapiFilter *filter);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_filter_set_operation(GstVaapiFilter *filter, GstVaapiFilterOp op,
|
||||||
|
const GValue *value);
|
||||||
|
|
||||||
|
GstVaapiFilterStatus
|
||||||
|
gst_vaapi_filter_process(GstVaapiFilter *filter, GstVaapiSurface *src_surface,
|
||||||
|
GstVaapiSurface *dst_surface, guint flags);
|
||||||
|
|
||||||
|
GArray *
|
||||||
|
gst_vaapi_filter_get_formats(GstVaapiFilter *filter);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_vaapi_filter_set_format(GstVaapiFilter *filter, GstVideoFormat format);
|
||||||
|
|
||||||
|
#endif /* GST_VAAPI_FILTER_H */
|
Loading…
Reference in a new issue