vaapipostproc: add mirror support

Adds vpp mirroring support to vaapipostproc.  Use
property video-direction.  Valid values are identity,
horiz or vert.  Default is identity (no mirror).

Closes #89

v2: Use GstVideoOrientationMethod enum
v3: Don't warn for VA_MIRROR_NONE.
    Use GST_TYPE_VIDEO_ORIENTATION_METHOD type.
v4: Query VAAPI caps when setting mirror value
    instead of during per-frame processing.
v5: Return TRUE in warning cases when setting mirror value.
This commit is contained in:
U. Artie Eoff 2019-05-13 16:39:33 -07:00 committed by Víctor Manuel Jáquez Leal
parent 38d25c65c3
commit 3ccf3f3334
6 changed files with 169 additions and 1 deletions

View file

@ -61,6 +61,7 @@ struct _GstVaapiFilter
GPtrArray *operations;
GstVideoFormat format;
GstVaapiScaleMethod scale_method;
GstVideoOrientationMethod video_direction;
GArray *formats;
GArray *forward_references;
GArray *backward_references;
@ -115,6 +116,17 @@ gst_vaapi_scale_method_get_type (void)
return g_type;
}
static const gchar *
gst_vaapi_get_video_direction_nick (GstVideoOrientationMethod method)
{
gpointer const klass = g_type_class_peek (GST_TYPE_VIDEO_ORIENTATION_METHOD);
GEnumValue *const e = g_enum_get_value (klass, method);
if (e)
return e->value_nick;
return "<unknown>";
}
GType
gst_vaapi_deinterlace_method_get_type (void)
{
@ -277,6 +289,7 @@ vpp_get_filter_caps (GstVaapiFilter * filter, VAProcFilterType type,
#define DEFAULT_FORMAT GST_VIDEO_FORMAT_UNKNOWN
#define DEFAULT_SCALING GST_VAAPI_SCALE_METHOD_DEFAULT
#define DEFAULT_VIDEO_DIRECTION GST_VIDEO_ORIENTATION_IDENTITY
enum
{
@ -297,6 +310,7 @@ enum
PROP_CONTRAST = GST_VAAPI_FILTER_OP_CONTRAST,
PROP_DEINTERLACING = GST_VAAPI_FILTER_OP_DEINTERLACING,
PROP_SCALING = GST_VAAPI_FILTER_OP_SCALING,
PROP_VIDEO_DIRECTION = GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
PROP_SKINTONE = GST_VAAPI_FILTER_OP_SKINTONE,
N_PROPERTIES
@ -420,6 +434,18 @@ init_properties (void)
GST_VAAPI_TYPE_SCALE_METHOD,
DEFAULT_SCALING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* GstVaapiFilter:video-direction:
*
* The video-direction to use, expressed as an enum value. See
* #GstVideoOrientationMethod.
*/
g_properties[PROP_VIDEO_DIRECTION] = g_param_spec_enum ("video-direction",
"Video Direction",
"Video direction: rotation and flipping",
GST_TYPE_VIDEO_ORIENTATION_METHOD,
DEFAULT_VIDEO_DIRECTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* GstVaapiFilter:skin-tone-enhancement:
*
@ -465,6 +491,7 @@ op_data_new (GstVaapiFilterOp op, GParamSpec * pspec)
case GST_VAAPI_FILTER_OP_FORMAT:
case GST_VAAPI_FILTER_OP_CROP:
case GST_VAAPI_FILTER_OP_SCALING:
case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
op_data->va_type = VAProcFilterNone;
break;
case GST_VAAPI_FILTER_OP_DENOISE:
@ -1330,6 +1357,9 @@ gst_vaapi_filter_set_operation (GstVaapiFilter * filter, GstVaapiFilterOp op,
return op_set_skintone (filter, op_data,
(value ? g_value_get_boolean (value) :
G_PARAM_SPEC_BOOLEAN (op_data->pspec)->default_value));
case GST_VAAPI_FILTER_OP_VIDEO_DIRECTION:
return gst_vaapi_filter_set_video_direction (filter, value ?
g_value_get_enum (value) : DEFAULT_VIDEO_DIRECTION);
default:
break;
}
@ -1362,6 +1392,7 @@ gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
guint i, num_filters = 0;
VAStatus va_status;
VARectangle src_rect, dst_rect;
guint va_mirror = from_GstVideoOrientationMethod (filter->video_direction);
if (!ensure_operations (filter))
return GST_VAAPI_FILTER_STATUS_ERROR_ALLOCATION_FAILED;
@ -1444,6 +1475,10 @@ gst_vaapi_filter_process_unlocked (GstVaapiFilter * filter,
pipeline_param->filters = filters;
pipeline_param->num_filters = num_filters;
#if VA_CHECK_VERSION(1,1,0)
pipeline_param->mirror_state = va_mirror;
#endif
// Reference frames for advanced deinterlacing
if (filter->forward_references->len > 0) {
pipeline_param->forward_references = (VASurfaceID *)
@ -1838,6 +1873,58 @@ gst_vaapi_filter_set_skintone (GstVaapiFilter * filter, gboolean enhance)
find_operation (filter, GST_VAAPI_FILTER_OP_SKINTONE), enhance);
}
/**
* gst_vaapi_filter_set_video_direction:
* @filter: a #GstVaapiFilter
* @method: the video direction (see #GstVideoOrientationMethod)
*
* Applies mirror/rotation to the video processing pipeline.
*
* Return value: %TRUE if the operation is supported, %FALSE otherwise.
*/
gboolean
gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
GstVideoOrientationMethod method)
{
g_return_val_if_fail (filter != NULL, FALSE);
switch (method) {
case GST_VIDEO_ORIENTATION_IDENTITY:
break;
case GST_VIDEO_ORIENTATION_HORIZ:
case GST_VIDEO_ORIENTATION_VERT:
{
#if VA_CHECK_VERSION(1,1,0)
VAProcPipelineCaps pipeline_caps;
guint va_mirror = from_GstVideoOrientationMethod (method);
VAStatus va_status = vaQueryVideoProcPipelineCaps (filter->va_display,
filter->va_context, NULL, 0, &pipeline_caps);
if (!vaapi_check_status (va_status, "vaQueryVideoProcPipelineCaps()"))
return FALSE;
if (!(pipeline_caps.mirror_flags & va_mirror)) {
GST_WARNING ("%s video-direction unsupported",
gst_vaapi_get_video_direction_nick (method));
return TRUE;
}
#else
GST_WARNING ("%s video-direction unsupported",
gst_vaapi_get_video_direction_nick (method));
return TRUE;
#endif
break;
}
default:
GST_WARNING ("%s video-direction unsupported or unimplemented",
gst_vaapi_get_video_direction_nick (method));
return TRUE;
}
filter->video_direction = method;
return TRUE;
}
static inline gfloat
op_get_float_default_value (GstVaapiFilter * filter,
GstVaapiFilterOpData * op_data)
@ -1915,3 +2002,11 @@ gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter)
return FALSE;
}
GstVideoOrientationMethod
gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter)
{
g_return_val_if_fail (filter != NULL, FALSE);
return DEFAULT_VIDEO_DIRECTION;
}

View file

@ -48,6 +48,8 @@ typedef struct _GstVaapiFilterOpInfo GstVaapiFilterOpInfo;
* @GST_VAAPI_FILTER_OP_BRIGHTNESS: Change brightness (float).
* @GST_VAAPI_FILTER_OP_CONTRAST: Change contrast (float).
* @GST_VAAPI_FILTER_OP_SCALING: Change scaling method (#GstVaapiScaleMethod).
* @GST_VAAPI_FILTER_OP_VIDEO_DIRECTION: Change video direction
* (#GstVideoOrientationMethod).
* @GST_VAAPI_FILTER_OP_SKINTONE: Skin tone enhancement (bool).
*
* The set of operations that could be applied to the filter.
@ -63,6 +65,7 @@ typedef enum {
GST_VAAPI_FILTER_OP_CONTRAST,
GST_VAAPI_FILTER_OP_DEINTERLACING,
GST_VAAPI_FILTER_OP_SCALING,
GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
GST_VAAPI_FILTER_OP_SKINTONE,
} GstVaapiFilterOp;
@ -246,6 +249,10 @@ gboolean
gst_vaapi_filter_set_scaling (GstVaapiFilter * filter,
GstVaapiScaleMethod method);
gboolean
gst_vaapi_filter_set_video_direction (GstVaapiFilter * filter,
GstVideoOrientationMethod method);
gboolean
gst_vaapi_filter_set_skintone (GstVaapiFilter * filter,
gboolean enhance);
@ -271,6 +278,9 @@ gst_vaapi_filter_get_contrast_default (GstVaapiFilter * filter);
GstVaapiScaleMethod
gst_vaapi_filter_get_scaling_default (GstVaapiFilter * filter);
GstVideoOrientationMethod
gst_vaapi_filter_get_video_direction_default (GstVaapiFilter * filter);
gboolean
gst_vaapi_filter_get_skintone_default (GstVaapiFilter * filter);

View file

@ -828,3 +828,27 @@ to_GstVaapiScaleMethod (guint flags)
}
return method;
}
/* VPP: translate GstVideoOrientationMethod into VA mirror flags */
guint
from_GstVideoOrientationMethod (guint value)
{
guint va_flags = 0;
switch (value) {
#if VA_CHECK_VERSION(1,1,0)
case GST_VIDEO_ORIENTATION_IDENTITY:
va_flags = VA_MIRROR_NONE;
break;
case GST_VIDEO_ORIENTATION_HORIZ:
va_flags = VA_MIRROR_HORIZONTAL;
break;
case GST_VIDEO_ORIENTATION_VERT:
va_flags = VA_MIRROR_VERTICAL;
break;
#endif
default:
break;
}
return va_flags;
}

View file

@ -147,4 +147,8 @@ G_GNUC_INTERNAL
guint
to_GstVaapiScaleMethod (guint flags);
G_GNUC_INTERNAL
guint
from_GstVideoOrientationMethod (guint value);
#endif /* GST_VAAPI_UTILS_H */

View file

@ -121,6 +121,7 @@ enum
PROP_BRIGHTNESS,
PROP_CONTRAST,
PROP_SCALE_METHOD,
PROP_VIDEO_DIRECTION,
PROP_SKIN_TONE_ENHANCEMENT,
};
@ -593,6 +594,16 @@ update_filter (GstVaapiPostproc * postproc)
postproc->flags &= ~(GST_VAAPI_POSTPROC_FLAG_SCALE);
}
if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION) {
if (!gst_vaapi_filter_set_video_direction (postproc->filter,
postproc->video_direction))
return FALSE;
if (gst_vaapi_filter_get_video_direction_default (postproc->filter) ==
postproc->video_direction)
postproc->flags &= ~(GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION);
}
if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_SKINTONE) {
if (!gst_vaapi_filter_set_skintone (postproc->filter,
postproc->skintone_enhance))
@ -1613,6 +1624,10 @@ gst_vaapipostproc_set_property (GObject * object,
postproc->scale_method = g_value_get_enum (value);
postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SCALE;
break;
case PROP_VIDEO_DIRECTION:
postproc->video_direction = g_value_get_enum (value);
postproc->flags |= GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION;
break;
case PROP_SKIN_TONE_ENHANCEMENT:
postproc->skintone_enhance = g_value_get_boolean (value);
postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SKINTONE;
@ -1674,6 +1689,9 @@ gst_vaapipostproc_get_property (GObject * object,
case PROP_SCALE_METHOD:
g_value_set_enum (value, postproc->scale_method);
break;
case PROP_VIDEO_DIRECTION:
g_value_set_enum (value, postproc->video_direction);
break;
case PROP_SKIN_TONE_ENHANCEMENT:
g_value_set_boolean (value, postproc->skintone_enhance);
break;
@ -1894,6 +1912,17 @@ gst_vaapipostproc_class_init (GstVaapiPostprocClass * klass)
g_object_class_install_property (object_class,
PROP_SCALE_METHOD, filter_op->pspec);
/**
* GstVaapiPostproc:video-direction:
*
* The video-direction to use, expressed as an enum value. See
* #GstVideoDirectionMethod.
*/
filter_op = find_filter_op (filter_ops, GST_VAAPI_FILTER_OP_VIDEO_DIRECTION);
if (filter_op)
g_object_class_install_property (object_class,
PROP_VIDEO_DIRECTION, filter_op->pspec);
/**
* GstVaapiPostproc:skin-tone-enhancement:
*

View file

@ -86,6 +86,7 @@ typedef enum
* @GST_VAAPI_POSTPROC_FLAG_DEINTERLACE: Deinterlacing.
* @GST_VAAPI_POSTPROC_FLAG_SIZE: Video scaling.
* @GST_VAAPI_POSTPROC_FLAG_SCALE: Video scaling mode.
* @GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION: Video rotation and flip/mirroring.
* @GST_VAAPI_POSTPROC_FLAG_SKINTONE: Skin tone enhancement.
*
* The set of operations that are to be performed for each frame.
@ -101,6 +102,8 @@ typedef enum
GST_VAAPI_POSTPROC_FLAG_CONTRAST = 1 << GST_VAAPI_FILTER_OP_CONTRAST,
GST_VAAPI_POSTPROC_FLAG_DEINTERLACE = 1 << GST_VAAPI_FILTER_OP_DEINTERLACING,
GST_VAAPI_POSTPROC_FLAG_SCALE = 1 << GST_VAAPI_FILTER_OP_SCALING,
GST_VAAPI_POSTPROC_FLAG_VIDEO_DIRECTION =
1 << GST_VAAPI_FILTER_OP_VIDEO_DIRECTION,
GST_VAAPI_POSTPROC_FLAG_SKINTONE = 1 << GST_VAAPI_FILTER_OP_SKINTONE,
/* Additional custom flags */
@ -160,8 +163,11 @@ struct _GstVaapiPostproc
gfloat denoise_level;
gfloat sharpen_level;
/* Color balance filter values */
GstVaapiScaleMethod scale_method;
GstVideoOrientationMethod video_direction;
/* Color balance filter values */
gfloat hue;
gfloat saturation;
gfloat brightness;