From ed9cc7c8d2b7a4fa987d4d8881a929b20569ca9d Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 30 Jul 2013 15:59:40 +0200 Subject: [PATCH] tests: filter: add support for deinterlacing. Add --deinterlace option to enable deinterlacing through explicit VA/VPP deinterlacing filter. However, if --deinterlace option is not set but the --deinterlace-flags option is set with "top-field-first", then the very basic bob deinterlacing filter is set through VA/VPP proc pipeline flags. --- tests/test-filter.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 127 insertions(+), 11 deletions(-) diff --git a/tests/test-filter.c b/tests/test-filter.c index 9b3f6c3..a96c033 100755 --- a/tests/test-filter.c +++ b/tests/test-filter.c @@ -31,6 +31,8 @@ static gchar *g_src_format_str; static gchar *g_crop_rect_str; static gchar *g_denoise_str; static gchar *g_sharpen_str; +static gchar *g_deinterlace_str; +static gchar *g_deinterlace_flags_str; static GOptionEntry g_options[] = { { "src-format", 's', @@ -49,6 +51,14 @@ static GOptionEntry g_options[] = { 0, G_OPTION_ARG_STRING, &g_sharpen_str, "set sharpening level", NULL }, + { "deinterlace", 0, + 0, + G_OPTION_ARG_STRING, &g_deinterlace_str, + "enable deinterlacing", NULL }, + { "deinterlace-flags", 0, + 0, + G_OPTION_ARG_STRING, &g_deinterlace_flags_str, + "deinterlacing flags", NULL }, { NULL, } }; @@ -79,7 +89,7 @@ pause(void) static GstVaapiSurface * create_test_surface(GstVaapiDisplay *display, guint width, guint height, - GError **error_ptr) + guint flags, GError **error_ptr) { GstVideoFormat format = GST_VIDEO_FORMAT_I420; GstVaapiSurface *surface = NULL; @@ -96,7 +106,7 @@ create_test_surface(GstVaapiDisplay *display, guint width, guint height, if (!surface) goto error_create_surface; - image = image_generate(display, format, width, height); + image = image_generate_full(display, format, width, height, flags); if (!image) goto error_create_image; @@ -224,6 +234,74 @@ parse_crop_rect(const gchar *str, GstVaapiRectangle *crop_rect) return FALSE; } +static gboolean +parse_enum(const gchar *str, GType type, gint default_value, + gint *out_value_ptr) +{ + gint out_value = default_value; + + g_return_val_if_fail(out_value_ptr != NULL, FALSE); + + if (str) { + GEnumClass * const enum_class = g_type_class_ref(type); + if (!enum_class) + return FALSE; + + const GEnumValue * const enum_value = + g_enum_get_value_by_nick(enum_class, str); + if (enum_value) + out_value = enum_value->value; + g_type_class_unref(enum_class); + + if (!enum_value) + return FALSE; + } + *out_value_ptr = out_value; + return TRUE; +} + +static gboolean +parse_flags(const gchar *str, GType type, guint *out_value_ptr) +{ + gchar **tokens = NULL; + gint i, value, out_value = 0; + gboolean success = FALSE; + + g_return_val_if_fail(out_value_ptr != NULL, FALSE); + + if (str) { + tokens = g_strsplit(str, ",", 32); + if (!tokens) + return FALSE; + + for (i = 0; tokens[i] != NULL; i++) { + if (!parse_enum(tokens[i], type, 0, &value)) + goto end; + out_value |= value; + } + } + *out_value_ptr = out_value; + success = TRUE; + +end: + g_strfreev(tokens); + return success; +} + +static inline gboolean +parse_deinterlace(const gchar *str, GstVaapiDeinterlaceMethod *deinterlace_ptr) +{ + return parse_enum(str, GST_VAAPI_TYPE_DEINTERLACE_METHOD, + GST_VAAPI_DEINTERLACE_METHOD_NONE, (gint *)deinterlace_ptr); +} + +static inline gboolean +parse_deinterlace_flags(const gchar *str, guint *deinterlace_flags_ptr) +{ + return parse_flags(str, GST_VAAPI_TYPE_DEINTERLACE_FLAGS, + deinterlace_flags_ptr); +} + int main(int argc, char *argv[]) { @@ -232,7 +310,10 @@ main(int argc, char *argv[]) GstVaapiSurface *src_surface, *dst_surface; GstVaapiFilter *filter = NULL; GstVaapiFilterStatus status; + GstVaapiDeinterlaceMethod deinterlace_method; + guint deinterlace_flags = 0; guint filter_flags = 0; + guint surface_flags = 0; gdouble denoise_level, sharpen_level; GError *error = NULL; @@ -252,6 +333,13 @@ main(int argc, char *argv[]) if (g_sharpen_str && !parse_double(g_sharpen_str, &sharpen_level)) g_error("failed to parse sharpening level"); + if (!parse_deinterlace(g_deinterlace_str, &deinterlace_method)) + g_error("failed to parse deinterlace method `%s'", g_deinterlace_str); + + if (!parse_deinterlace_flags(g_deinterlace_flags_str, &deinterlace_flags)) + g_error("failed to parse deinterlace flags `%s'", + g_deinterlace_flags_str); + display = video_output_create_display(NULL); if (!display) g_error("failed to create VA display"); @@ -260,15 +348,6 @@ main(int argc, char *argv[]) if (!window) g_error("failed to create window"); - src_surface = create_test_surface(display, src_width, src_height, &error); - if (!src_surface) - g_error("failed to create source VA surface: %s", error->message); - - dst_surface = gst_vaapi_surface_new(display, GST_VAAPI_CHROMA_TYPE_YUV420, - dst_width, dst_height); - if (!dst_surface) - g_error("failed to create target VA surface"); - filter = gst_vaapi_filter_new(display); if (!filter) g_error("failed to create video processing pipeline"); @@ -303,6 +382,41 @@ main(int argc, char *argv[]) g_error("failed to set sharpening level"); } + if (deinterlace_method != GST_VAAPI_DEINTERLACE_METHOD_NONE) { + printf("Enable deinterlacing: %s\n", g_deinterlace_str); + + if (!gst_vaapi_filter_set_deinterlacing(filter, deinterlace_method, + deinterlace_flags)) + g_error("failed to set deinterlacing method"); + } + else if (deinterlace_flags) { + if (deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_TFF) + filter_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; + else + filter_flags = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + } + + if (deinterlace_method != GST_VAAPI_DEINTERLACE_METHOD_NONE || + deinterlace_flags) { + if (!(deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD)) + surface_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD | + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + else if (deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_TFF) + surface_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; + else + surface_flags = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + } + + src_surface = create_test_surface(display, src_width, src_height, + surface_flags, &error); + if (!src_surface) + g_error("failed to create source VA surface: %s", error->message); + + dst_surface = gst_vaapi_surface_new(display, GST_VAAPI_CHROMA_TYPE_YUV420, + dst_width, dst_height); + if (!dst_surface) + g_error("failed to create target VA surface"); + status = gst_vaapi_filter_process(filter, src_surface, dst_surface, filter_flags); if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) @@ -326,5 +440,7 @@ main(int argc, char *argv[]) g_free(g_crop_rect_str); g_free(g_denoise_str); g_free(g_sharpen_str); + g_free(g_deinterlace_str); + g_free(g_deinterlace_flags_str); return 0; } -- 2.7.4