2 * test-filter.c - Test GstVaapiFilter
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6 * Copyright (C) 2012-2013 Intel Corporation
7 * Author: Halley Zhao <halley.zhao@intel.com>
8 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301 USA
26 #include "gst/vaapi/sysdeps.h"
28 #include <gst/vaapi/gstvaapifilter.h>
29 #include <gst/vaapi/gstvaapiwindow.h>
33 static gchar *g_src_format_str;
34 static gchar *g_crop_rect_str;
35 static gchar *g_denoise_str;
36 static gchar *g_sharpen_str;
37 static gchar *g_deinterlace_str;
38 static gchar *g_deinterlace_flags_str;
40 static GOptionEntry g_options[] = {
43 G_OPTION_ARG_STRING, &g_src_format_str,
44 "source surface format", NULL },
47 G_OPTION_ARG_STRING, &g_crop_rect_str,
48 "cropping rectangle", NULL },
51 G_OPTION_ARG_STRING, &g_denoise_str,
52 "set noise reduction level", NULL },
55 G_OPTION_ARG_STRING, &g_sharpen_str,
56 "set sharpening level", NULL },
59 G_OPTION_ARG_STRING, &g_deinterlace_str,
60 "enable deinterlacing", NULL },
61 { "deinterlace-flags", 0,
63 G_OPTION_ARG_STRING, &g_deinterlace_flags_str,
64 "deinterlacing flags", NULL },
68 #define APP_ERROR app_error_quark()
74 if (g_once_init_enter(&g_quark)) {
75 gsize quark = (gsize)g_quark_from_static_string("AppError");
76 g_once_init_leave(&g_quark, quark);
83 APP_ERROR_CREATE_TEST_SURFACE,
89 g_print("Press any key to continue...\n");
93 static GstVaapiSurface *
94 create_test_surface(GstVaapiDisplay *display, guint width, guint height,
95 guint flags, GError **error_ptr)
97 GstVideoFormat format = GST_VIDEO_FORMAT_I420;
98 GstVaapiSurface *surface = NULL;
99 GstVaapiImage *image = NULL;
100 GError *error = NULL;
102 if (g_src_format_str) {
103 format = gst_vaapi_video_format_from_string(g_src_format_str);
104 if (format == GST_VIDEO_FORMAT_UNKNOWN)
105 goto error_invalid_format;
108 surface = gst_vaapi_surface_new_with_format(display, format, width, height);
110 goto error_create_surface;
112 image = image_generate_full(display, format, width, height, flags);
114 goto error_create_image;
116 if (!image_upload(image, surface))
117 goto error_upload_image;
119 gst_vaapi_object_unref(image);
123 error_invalid_format:
124 error = g_error_new(APP_ERROR, APP_ERROR_CREATE_TEST_SURFACE,
125 "unknown format %s", g_src_format_str);
127 error_create_surface:
128 error = g_error_new(APP_ERROR, APP_ERROR_CREATE_TEST_SURFACE,
129 "unsupported format %s", gst_vaapi_video_format_to_string(format));
132 error = g_error_new(APP_ERROR, APP_ERROR_CREATE_TEST_SURFACE,
133 "unsupported %s image", gst_vaapi_video_format_to_string(format));
136 error = g_error_new(APP_ERROR, APP_ERROR_CREATE_TEST_SURFACE,
137 "failed to upload %s image", gst_vaapi_video_format_to_string(format));
141 gst_vaapi_object_unref(image);
143 gst_vaapi_object_unref(surface);
152 dump_operation(GstVaapiFilterOpInfo *op_info)
154 GParamSpec * const pspec = op_info->pspec;
155 GValue value = G_VALUE_INIT;
161 g_print(" %s: ", g_param_spec_get_name(pspec));
162 g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
163 g_param_value_set_default(pspec, &value);
164 value_str = g_strdup_value_contents(&value);
165 g_print("%s (default: %s)\n", G_VALUE_TYPE_NAME(&value),
166 value_str ? value_str : "<unknown>");
171 dump_operations(GstVaapiFilter *filter)
173 GPtrArray * const ops = gst_vaapi_filter_get_operations(filter);
179 g_print("%u operations\n", ops->len);
180 for (i = 0; i < ops->len; i++)
181 dump_operation(g_ptr_array_index(ops, i));
182 g_ptr_array_unref(ops);
186 dump_formats(GstVaapiFilter *filter)
188 GArray * const formats = gst_vaapi_filter_get_formats(filter);
194 g_print("%u formats\n", formats->len);
195 for (i = 0; i < formats->len; i++) {
196 GstVideoFormat format = g_array_index(formats, GstVideoFormat, i);
197 g_print(" %s\n", gst_vaapi_video_format_to_string(format));
199 g_array_unref(formats);
203 parse_double(const gchar *str, gdouble *out_value_ptr)
205 gchar *endptr = NULL;
208 g_return_val_if_fail(out_value_ptr != NULL, FALSE);
211 out_value = g_ascii_strtod(str, &endptr);
212 if (!endptr || *endptr != '\0' || errno == ERANGE)
215 *out_value_ptr = out_value;
220 parse_crop_rect(const gchar *str, GstVaapiRectangle *crop_rect)
223 // Format: <WIDTH> 'x' <HEIGHT>
224 if (sscanf(str, "%ux%u", &crop_rect->width, &crop_rect->height) == 2) {
230 // Format: '('? <X> ',' <Y> ')'? <WIDTH> 'x' <HEIGHT>
231 if (sscanf(str, "(%d,%d):%ux%u", &crop_rect->x, &crop_rect->y,
232 &crop_rect->width, &crop_rect->height) == 4 ||
233 sscanf(str, "%d,%d:%ux%u", &crop_rect->x, &crop_rect->y,
234 &crop_rect->width, &crop_rect->height) == 4)
241 parse_enum(const gchar *str, GType type, gint default_value,
244 gint out_value = default_value;
246 g_return_val_if_fail(out_value_ptr != NULL, FALSE);
249 GEnumClass * const enum_class = g_type_class_ref(type);
253 const GEnumValue * const enum_value =
254 g_enum_get_value_by_nick(enum_class, str);
256 out_value = enum_value->value;
257 g_type_class_unref(enum_class);
262 *out_value_ptr = out_value;
267 parse_flags(const gchar *str, GType type, guint *out_value_ptr)
269 gchar **tokens = NULL;
270 gint i, value, out_value = 0;
271 gboolean success = FALSE;
273 g_return_val_if_fail(out_value_ptr != NULL, FALSE);
276 tokens = g_strsplit(str, ",", 32);
280 for (i = 0; tokens[i] != NULL; i++) {
281 if (!parse_enum(tokens[i], type, 0, &value))
286 *out_value_ptr = out_value;
294 static inline gboolean
295 parse_deinterlace(const gchar *str, GstVaapiDeinterlaceMethod *deinterlace_ptr)
297 g_return_val_if_fail(deinterlace_ptr != NULL, FALSE);
300 *deinterlace_ptr = GST_VAAPI_DEINTERLACE_METHOD_NONE;
303 return parse_enum(str, GST_VAAPI_TYPE_DEINTERLACE_METHOD,
304 GST_VAAPI_DEINTERLACE_METHOD_NONE, (gint *)deinterlace_ptr);
307 static inline gboolean
308 parse_deinterlace_flags(const gchar *str, guint *deinterlace_flags_ptr)
310 return parse_flags(str, GST_VAAPI_TYPE_DEINTERLACE_FLAGS,
311 deinterlace_flags_ptr);
315 main(int argc, char *argv[])
317 GstVaapiDisplay *display;
318 GstVaapiWindow *window;
319 GstVaapiSurface *src_surface, *dst_surface;
320 GstVaapiFilter *filter = NULL;
321 GstVaapiFilterStatus status;
322 GstVaapiDeinterlaceMethod deinterlace_method;
323 guint deinterlace_flags = 0;
324 guint filter_flags = 0;
325 guint surface_flags = 0;
326 gdouble denoise_level, sharpen_level;
327 GError *error = NULL;
329 static const guint src_width = 320;
330 static const guint src_height = 240;
331 static const guint dst_width = 480;
332 static const guint dst_height = 360;
333 static const guint win_width = 640;
334 static const guint win_height = 480;
336 if (!video_output_init(&argc, argv, g_options))
337 g_error("failed to initialize video output subsystem");
339 if (g_denoise_str && !parse_double(g_denoise_str, &denoise_level))
340 g_error("failed to parse noise reduction level");
342 if (g_sharpen_str && !parse_double(g_sharpen_str, &sharpen_level))
343 g_error("failed to parse sharpening level");
345 if (!parse_deinterlace(g_deinterlace_str, &deinterlace_method))
346 g_error("failed to parse deinterlace method `%s'", g_deinterlace_str);
348 if (!parse_deinterlace_flags(g_deinterlace_flags_str, &deinterlace_flags))
349 g_error("failed to parse deinterlace flags `%s'",
350 g_deinterlace_flags_str);
352 display = video_output_create_display(NULL);
354 g_error("failed to create VA display");
356 window = video_output_create_window(display, win_width, win_height);
358 g_error("failed to create window");
360 filter = gst_vaapi_filter_new(display);
362 g_error("failed to create video processing pipeline");
364 dump_operations(filter);
365 dump_formats(filter);
367 if (g_crop_rect_str) {
368 GstVaapiRectangle crop_rect;
370 if (!parse_crop_rect(g_crop_rect_str, &crop_rect))
371 g_error("failed to parse cropping rectangle");
373 printf("Frame cropping: (%d,%d), size %ux%u\n",
374 crop_rect.x, crop_rect.y, crop_rect.width, crop_rect.height);
376 if (!gst_vaapi_filter_set_cropping_rectangle(filter, &crop_rect))
377 g_error("failed to set cropping rectangle");
381 printf("Noise reduction level: %f\n", denoise_level);
383 if (!gst_vaapi_filter_set_denoising_level(filter, denoise_level))
384 g_error("failed to set denoising level");
388 printf("Sharpening level: %f\n", sharpen_level);
390 if (!gst_vaapi_filter_set_sharpening_level(filter, sharpen_level))
391 g_error("failed to set sharpening level");
394 if (deinterlace_method != GST_VAAPI_DEINTERLACE_METHOD_NONE) {
395 printf("Enable deinterlacing: %s\n", g_deinterlace_str);
397 if (!gst_vaapi_filter_set_deinterlacing(filter, deinterlace_method,
399 g_error("failed to set deinterlacing method");
401 else if (deinterlace_flags) {
402 if (deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD)
403 filter_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
405 filter_flags = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
408 if (deinterlace_method != GST_VAAPI_DEINTERLACE_METHOD_NONE ||
410 if (!(deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_ONEFIELD))
411 surface_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD |
412 GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
413 else if (deinterlace_flags & GST_VAAPI_DEINTERLACE_FLAG_TOPFIELD)
414 surface_flags = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
416 surface_flags = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
419 src_surface = create_test_surface(display, src_width, src_height,
420 surface_flags, &error);
422 g_error("failed to create source VA surface: %s", error->message);
424 dst_surface = gst_vaapi_surface_new(display, GST_VAAPI_CHROMA_TYPE_YUV420,
425 dst_width, dst_height);
427 g_error("failed to create target VA surface");
429 status = gst_vaapi_filter_process(filter, src_surface, dst_surface,
431 if (status != GST_VAAPI_FILTER_STATUS_SUCCESS)
432 g_error("failed to process video filters");
434 gst_vaapi_window_show(window);
436 if (!gst_vaapi_window_put_surface(window, dst_surface, NULL, NULL,
437 GST_VAAPI_PICTURE_STRUCTURE_FRAME))
438 g_error("failed to render target surface");
442 gst_vaapi_filter_unref(filter);
443 gst_vaapi_object_unref(dst_surface);
444 gst_vaapi_object_unref(src_surface);
445 gst_vaapi_window_unref(window);
446 gst_vaapi_display_unref(display);
448 g_free(g_src_format_str);
449 g_free(g_crop_rect_str);
450 g_free(g_denoise_str);
451 g_free(g_sharpen_str);
452 g_free(g_deinterlace_str);
453 g_free(g_deinterlace_flags_str);