filter: add initial support for deinterlacing.

Add basic deinterlacing support, i.e. bob-deinterlacing whereby only
the selected field from the input surface is kept for the target surface.
Setting gst_vaapi_filter_set_deinterlacing() method argument to
GST_VAAPI_DEINTERLACE_METHOD_NONE means to disable deinterlacing.

Also move GstVaapiDeinterlaceMethod definition from vaapipostproc plug-in
to libgstvaapi core library.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
Zhao Halley 2013-07-29 09:23:50 +08:00 committed by Gwenole Beauchesne
parent 1d222d3b4a
commit 944a7bd077
7 changed files with 269 additions and 45 deletions

View file

@ -393,6 +393,7 @@ gst_vaapi_filter_set_hue
gst_vaapi_filter_set_saturation
gst_vaapi_filter_set_brightness
gst_vaapi_filter_set_saturation
gst_vaapi_filter_set_deinterlacing
<SUBSECTION Standard>
GST_VAAPI_FILTER
</SECTION>

162
gst-libs/gst/vaapi/gstvaapifilter.c Normal file → Executable file
View file

@ -67,6 +67,60 @@ struct _GstVaapiFilter {
guint use_crop_rect : 1;
};
/* ------------------------------------------------------------------------- */
/* --- VPP Types --- */
/* ------------------------------------------------------------------------- */
GType
gst_vaapi_deinterlace_method_get_type(void)
{
static gsize g_type = 0;
static const GEnumValue enum_values[] = {
{ GST_VAAPI_DEINTERLACE_METHOD_NONE,
"Disable deinterlacing", "none" },
{ GST_VAAPI_DEINTERLACE_METHOD_BOB,
"Bob deinterlacing", "bob" },
#if USE_VA_VPP
{ GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
"Weave deinterlacing", "weave" },
{ GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
"Motion adaptive deinterlacing", "motion-adaptive" },
{ GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
"Motion compensated deinterlacing", "motion-compensated" },
#endif
{ 0, NULL, NULL },
};
if (g_once_init_enter(&g_type)) {
const GType type =
g_enum_register_static("GstVaapiDeinterlaceMethod", enum_values);
g_once_init_leave(&g_type, type);
}
return g_type;
}
GType
gst_vaapi_deinterlace_flags_get_type(void)
{
static gsize g_type = 0;
static const GEnumValue enum_values[] = {
{ GST_VAAPI_DEINTERLACE_FLAG_TFF,
"Top-field first", "top-field-first" },
{ GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD,
"One field", "one-field" },
{ 0, NULL, NULL }
};
if (g_once_init_enter(&g_type)) {
const GType type =
g_enum_register_static("GstVaapiDeinterlaceFlags", enum_values);
g_once_init_leave(&g_type, type);
}
return g_type;
}
/* ------------------------------------------------------------------------- */
/* --- VPP Helpers --- */
/* ------------------------------------------------------------------------- */
@ -188,6 +242,7 @@ enum {
PROP_SATURATION = GST_VAAPI_FILTER_OP_SATURATION,
PROP_BRIGHTNESS = GST_VAAPI_FILTER_OP_BRIGHTNESS,
PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
N_PROPERTIES
};
@ -299,6 +354,20 @@ init_properties(void)
"The color contrast value",
0.0, 2.0, 1.0,
G_PARAM_READWRITE);
/**
* GstVaapiFilter:deinterlace-method:
*
* The deinterlacing algorithm to apply, expressed a an enum
* value. See #GstVaapiDeinterlaceMethod.
*/
g_properties[PROP_DEINTERLACING] =
g_param_spec_enum("deinterlace",
"Deinterlacing Method",
"Deinterlacing method to apply",
GST_VAAPI_TYPE_DEINTERLACE_METHOD,
GST_VAAPI_DEINTERLACE_METHOD_NONE,
G_PARAM_READWRITE);
}
static void
@ -354,6 +423,11 @@ op_data_new(GstVaapiFilterOp op, GParamSpec *pspec)
op_data->va_cap_size = sizeof(VAProcFilterCapColorBalance);
op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferColorBalance);
break;
case GST_VAAPI_FILTER_OP_DEINTERLACING:
op_data->va_type = VAProcFilterDeinterlacing;
op_data->va_cap_size = sizeof(VAProcFilterCapDeinterlacing);
op_data->va_buffer_size = sizeof(VAProcFilterParameterBufferDeinterlacing);
break;
default:
g_assert(0 && "unsupported operation");
goto error;
@ -409,9 +483,14 @@ op_data_ensure_caps(GstVaapiFilterOpData *op_data, gpointer filter_caps,
if (i == num_filter_caps)
return FALSE;
}
op_data->va_caps = g_memdup(filter_cap,
op_data->va_cap_size * num_filter_caps);
return op_data->va_caps != NULL;
if (!op_data->va_caps)
return FALSE;
op_data->va_num_caps = num_filter_caps;
return TRUE;
}
/* Scale the filter value wrt. library spec and VA driver spec */
@ -681,6 +760,59 @@ op_set_color_balance(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
return success;
}
/* Update deinterlace filter */
#if USE_VA_VPP
static gboolean
op_set_deinterlace_unlocked(GstVaapiFilter *filter,
GstVaapiFilterOpData *op_data, GstVaapiDeinterlaceMethod method,
guint flags)
{
VAProcFilterParameterBufferDeinterlacing *buf;
const VAProcFilterCapDeinterlacing *filter_caps;
VAProcDeinterlacingType algorithm;
guint i;
if (!op_data || !op_ensure_buffer(filter, op_data))
return FALSE;
op_data->is_enabled = (method != GST_VAAPI_DEINTERLACE_METHOD_NONE);
if (!op_data->is_enabled)
return TRUE;
algorithm = from_GstVaapiDeinterlaceMethod(method);
for (i = 0, filter_caps = op_data->va_caps; i < op_data->va_num_caps; i++) {
if (filter_caps[i].type == algorithm)
break;
}
if (i == op_data->va_num_caps)
return FALSE;
buf = vaapi_map_buffer(filter->va_display, op_data->va_buffer);
if (!buf)
return FALSE;
buf->type = op_data->va_type;
buf->algorithm = algorithm;
buf->flags = from_GstVaapiDeinterlaceFlags(flags);
vaapi_unmap_buffer(filter->va_display, op_data->va_buffer, NULL);
return TRUE;
}
#endif
static inline gboolean
op_set_deinterlace(GstVaapiFilter *filter, GstVaapiFilterOpData *op_data,
GstVaapiDeinterlaceMethod method, guint flags)
{
gboolean success = FALSE;
#if USE_VA_VPP
GST_VAAPI_DISPLAY_LOCK(filter->display);
success = op_set_deinterlace_unlocked(filter, op_data, method, flags);
GST_VAAPI_DISPLAY_UNLOCK(filter->display);
#endif
return success;
}
/* ------------------------------------------------------------------------- */
/* --- Surface Formats --- */
/* ------------------------------------------------------------------------- */
@ -1004,6 +1136,11 @@ gst_vaapi_filter_set_operation(GstVaapiFilter *filter, GstVaapiFilterOp op,
return op_set_color_balance(filter, op_data,
(value ? g_value_get_float(value) :
G_PARAM_SPEC_FLOAT(op_data->pspec)->default_value));
case GST_VAAPI_FILTER_OP_DEINTERLACING:
return op_set_deinterlace(filter, op_data,
(value ? g_value_get_enum(value) :
G_PARAM_SPEC_ENUM(op_data->pspec)->default_value), 0);
break;
default:
break;
}
@ -1322,3 +1459,26 @@ gst_vaapi_filter_set_contrast(GstVaapiFilter *filter, gfloat value)
return op_set_color_balance(filter,
find_operation(filter, GST_VAAPI_FILTER_OP_CONTRAST), value);
}
/**
* gst_vaapi_filter_set_deinterlacing:
* @filter: a #GstVaapiFilter
* @method: the deinterlacing algorithm (see #GstVaapiDeinterlaceMethod)
* @flags: the additional flags
*
* Applies deinterlacing to the video processing pipeline. If @method
* is not @GST_VAAPI_DEINTERLACE_METHOD_NONE, then @flags could
* represent the initial picture structure of the source frame.
*
* Return value: %TRUE if the operation is supported, %FALSE otherwise.
*/
gboolean
gst_vaapi_filter_set_deinterlacing(GstVaapiFilter *filter,
GstVaapiDeinterlaceMethod method, guint flags)
{
g_return_val_if_fail(filter != NULL, FALSE);
return op_set_deinterlace(filter,
find_operation(filter, GST_VAAPI_FILTER_OP_DEINTERLACING), method,
flags);
}

52
gst-libs/gst/vaapi/gstvaapifilter.h Normal file → Executable file
View file

@ -51,6 +51,7 @@ typedef enum {
GST_VAAPI_FILTER_OP_SATURATION,
GST_VAAPI_FILTER_OP_BRIGHTNESS,
GST_VAAPI_FILTER_OP_CONTRAST,
GST_VAAPI_FILTER_OP_DEINTERLACING,
} GstVaapiFilterOp;
/**
@ -85,6 +86,53 @@ typedef enum {
GST_VAAPI_FILTER_STATUS_ERROR_UNSUPPORTED_FORMAT,
} GstVaapiFilterStatus;
/**
* GstVaapiDeinterlaceMethod:
* @GST_VAAPI_DEINTERLACE_METHOD_NONE: No deinterlacing.
* @GST_VAAPI_DEINTERLACE_METHOD_BOB: Basic bob deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_WEAVE: Weave deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: Motion adaptive
* deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: Motion compensated
* deinterlacing algorithm.
*
* Deinterlacing algorithms.
*/
typedef enum {
GST_VAAPI_DEINTERLACE_METHOD_NONE,
GST_VAAPI_DEINTERLACE_METHOD_BOB,
GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
} GstVaapiDeinterlaceMethod;
/**
* GstVaapiDeinterlaceFlags:
* @GST_VAAPI_DEINTERLACE_FLAG_TFF: Top-field first. If this flag is
* not set, then bottom-field first order is assumed.
* @GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD: The input frame represents a
* single field. If this flag is not set, then the whole frame holds
* two fields.
*
* The set of gst_vaapi_filter_set_deinterlacing() flags.
*/
typedef enum {
GST_VAAPI_DEINTERLACE_FLAG_TFF = 1 << 31,
GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD = 1 << 30,
} GstVaapiDeinterlaceFlags;
#define GST_VAAPI_TYPE_DEINTERLACE_METHOD \
gst_vaapi_deinterlace_method_get_type()
#define GST_VAAPI_TYPE_DEINTERLACE_FLAGS \
gst_vaapi_deinterlace_flags_get_type()
GType
gst_vaapi_deinterlace_method_get_type(void) G_GNUC_CONST;
GType
gst_vaapi_deinterlace_flags_get_type(void) G_GNUC_CONST;
GstVaapiFilter *
gst_vaapi_filter_new(GstVaapiDisplay *display);
@ -137,4 +185,8 @@ gst_vaapi_filter_set_brightness(GstVaapiFilter *filter, gfloat value);
gboolean
gst_vaapi_filter_set_contrast(GstVaapiFilter *filter, gfloat value);
gboolean
gst_vaapi_filter_set_deinterlacing(GstVaapiFilter *filter,
GstVaapiDeinterlaceMethod method, guint flags);
#endif /* GST_VAAPI_FILTER_H */

View file

@ -25,9 +25,14 @@
#include "gstvaapiutils.h"
#include "gstvaapisurface.h"
#include "gstvaapisubpicture.h"
#include "gstvaapifilter.h"
#include <stdio.h>
#include <stdarg.h>
#if USE_VA_VPP
# include <va/va_vpp.h>
#endif
#define DEBUG 1
#include "gstvaapidebug.h"
@ -433,3 +438,44 @@ to_GstVaapiRotation(guint value)
GST_ERROR("unsupported VA-API rotation value %d", value);
return GST_VAAPI_ROTATION_0;
}
/* VPP: translate GstVaapiDeinterlaceMethod to VA deinterlacing algorithm */
guint
from_GstVaapiDeinterlaceMethod(guint value)
{
switch (value) {
case GST_VAAPI_DEINTERLACE_METHOD_NONE:
return 0;
#if USE_VA_VPP
case GST_VAAPI_DEINTERLACE_METHOD_BOB:
return VAProcDeinterlacingBob;
case GST_VAAPI_DEINTERLACE_METHOD_WEAVE:
return VAProcDeinterlacingWeave;
case GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE:
return VAProcDeinterlacingMotionAdaptive;
case GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED:
return VAProcDeinterlacingMotionCompensated;
#endif
}
GST_ERROR("unsupported GstVaapiDeinterlaceMethod value %d", value);
return 0;
}
/* VPP: translate GstVaapiDeinterlaceFlags into VA deinterlacing flags */
guint
from_GstVaapiDeinterlaceFlags(guint flags)
{
guint va_flags = 0;
#if USE_VA_VPP
if (!(flags & GST_VAAPI_DEINTERLACE_FLAG_TFF))
va_flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
if (flags & GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD) {
va_flags |= VA_DEINTERLACING_ONE_FIELD;
if (!(flags & GST_VAAPI_DEINTERLACE_FLAG_TFF))
va_flags |= VA_DEINTERLACING_BOTTOM_FIELD;
}
#endif
return va_flags;
}

View file

@ -109,4 +109,12 @@ G_GNUC_INTERNAL
guint
to_GstVaapiRotation(guint value);
G_GNUC_INTERNAL
guint
from_GstVaapiDeinterlaceMethod(guint value);
G_GNUC_INTERNAL
guint
from_GstVaapiDeinterlaceFlags(guint flags);
#endif /* GST_VAAPI_UTILS_H */

30
gst/vaapi/gstvaapipostproc.c Normal file → Executable file
View file

@ -149,36 +149,6 @@ gst_vaapi_deinterlace_mode_get_type(void)
return deinterlace_mode_type;
}
#define GST_VAAPI_TYPE_DEINTERLACE_METHOD \
gst_vaapi_deinterlace_method_get_type()
static GType
gst_vaapi_deinterlace_method_get_type(void)
{
static GType deinterlace_method_type = 0;
static const GEnumValue method_types[] = {
{ GST_VAAPI_DEINTERLACE_METHOD_BOB,
"Bob deinterlacing", "bob" },
#if 0
/* VA/VPP */
{ GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
"Weave deinterlacing", "weave" },
{ GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
"Motion adaptive deinterlacing", "motion-adaptive" },
{ GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
"Motion compensated deinterlacing", "motion-compensated" },
#endif
{ 0, NULL, NULL },
};
if (!deinterlace_method_type) {
deinterlace_method_type =
g_enum_register_static("GstVaapiDeinterlaceMethod", method_types);
}
return deinterlace_method_type;
}
static inline GstVaapiPostproc *
get_vaapipostproc_from_pad(GstPad *pad)
{

15
gst/vaapi/gstvaapipostproc.h Normal file → Executable file
View file

@ -26,6 +26,7 @@
#include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/gstvaapisurfacepool.h>
#include <gst/vaapi/gstvaapifilter.h>
G_BEGIN_DECLS
@ -68,20 +69,6 @@ typedef enum {
GST_VAAPI_DEINTERLACE_MODE_DISABLED,
} GstVaapiDeinterlaceMode;
/**
* GstVaapiDeinterlaceMethod:
* @GST_VAAPI_DEINTERLACE_METHOD_BOB: Basic bob deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_WEAVE: Weave deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE: Motion adaptive deinterlacing algorithm.
* @GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED: Motion compensated deinterlacing algorithm.
*/
typedef enum {
GST_VAAPI_DEINTERLACE_METHOD_BOB = 1,
GST_VAAPI_DEINTERLACE_METHOD_WEAVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_ADAPTIVE,
GST_VAAPI_DEINTERLACE_METHOD_MOTION_COMPENSATED,
} GstVaapiDeinterlaceMethod;
struct _GstVaapiPostproc {
/*< private >*/
GstElement parent_instance;