From cdd86d025a7c2e1c00e7a86731168793e6104276 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 11 Feb 2015 13:32:25 +0100 Subject: [PATCH] video-scaler: add 2d scaler Make a convenience function that combines 2 scalers to perform a 2d scale. This removes quite a bit of overhead in method calls when doing a typical scale and it also can reuse a piece of unused memory in the vertical scaler. Use the 2d scaler in video-converter and remove the other scalers and temp memory. --- gst-libs/gst/video/video-converter.c | 168 +++------- gst-libs/gst/video/video-scaler.c | 452 +++++++++++++++------------ gst-libs/gst/video/video-scaler.h | 8 + win32/common/libgstvideo.def | 1 + 4 files changed, 306 insertions(+), 323 deletions(-) diff --git a/gst-libs/gst/video/video-converter.c b/gst-libs/gst/video/video-converter.c index 99bdad7733..d9d521e7d5 100644 --- a/gst-libs/gst/video/video-converter.c +++ b/gst-libs/gst/video/video-converter.c @@ -246,9 +246,6 @@ struct _GstVideoConverter GstVideoFrame *dest; /* fastpath */ - ConverterAlloc *flines; - gpointer *lineptr; - GstVideoFormat fformat[4]; gint fin_x[4]; gint fin_y[4]; @@ -1947,7 +1944,6 @@ gst_video_converter_free (GstVideoConverter * convert) g_free (convert->gamma_enc.gamma_table); g_free (convert->tmpline); - g_free (convert->lineptr); g_free (convert->borderline); if (convert->config) @@ -1959,8 +1955,6 @@ gst_video_converter_free (GstVideoConverter * convert) if (convert->fh_scaler[i]) gst_video_scaler_free (convert->fh_scaler[i]); } - if (convert->flines) - converter_alloc_free (convert->flines); g_slice_free (GstVideoConverter, convert); } @@ -3386,35 +3380,6 @@ convert_plane_copy (GstVideoConverter * convert, convert->fout_width[plane], convert->fout_height[plane]); } -static void -convert_plane_h (GstVideoConverter * convert, - const GstVideoFrame * src, GstVideoFrame * dest, gint plane) -{ - gint i; - gint in_x, in_y, out_x, out_y, out_width, out_height; - GstVideoFormat format; - GstVideoScaler *h_scaler; - guint8 *s, *d; - gint splane = convert->fsplane[plane]; - - in_x = convert->fin_x[splane]; - in_y = convert->fin_y[splane]; - out_x = convert->fout_x[plane]; - out_y = convert->fout_y[plane]; - out_width = convert->fout_width[plane]; - out_height = convert->fout_height[plane]; - format = convert->fformat[plane]; - h_scaler = convert->fh_scaler[plane]; - - for (i = 0; i < out_height; i++) { - s = FRAME_GET_PLANE_LINE (src, splane, i + in_y); - d = FRAME_GET_PLANE_LINE (dest, plane, i + out_y); - - gst_video_scaler_horizontal (h_scaler, format, - s + in_x, d + out_x, 0, out_width); - } -} - static void convert_plane_h_double (GstVideoConverter * convert, const GstVideoFrame * src, GstVideoFrame * dest, gint plane) @@ -3451,44 +3416,6 @@ convert_plane_h_halve (GstVideoConverter * convert, convert->fout_height[plane]); } -static void -convert_plane_v (GstVideoConverter * convert, - const GstVideoFrame * src, GstVideoFrame * dest, gint plane) -{ - gint i; - gint in_x, in_y, out_x, out_y, out_width, out_height; - GstVideoFormat format; - GstVideoScaler *v_scaler; - gpointer *lines; - gint splane = convert->fsplane[plane]; - - in_x = convert->fin_x[splane]; - in_y = convert->fin_y[splane]; - out_x = convert->fout_x[plane]; - out_y = convert->fout_y[plane]; - out_width = convert->fout_width[plane]; - out_height = convert->fout_height[plane]; - format = convert->fformat[plane]; - v_scaler = convert->fv_scaler[plane]; - lines = convert->lineptr; - - for (i = 0; i < out_height; i++) { - guint in, n_taps, j; - guint8 *s, *d; - - gst_video_scaler_get_coeff (v_scaler, i, &in, &n_taps); - for (j = 0; j < n_taps; j++) { - s = FRAME_GET_PLANE_LINE (src, splane, in + in_y + j); - s += in_x; - lines[j] = s; - } - - d = FRAME_GET_PLANE_LINE (dest, plane, i + out_y); - gst_video_scaler_vertical (v_scaler, format, lines, d + out_x, i, - out_width); - } -} - static void convert_plane_v_double (GstVideoConverter * convert, const GstVideoFrame * src, GstVideoFrame * dest, gint plane) @@ -3530,55 +3457,6 @@ convert_plane_v_halve (GstVideoConverter * convert, convert->fout_width[plane], convert->fout_height[plane]); } -static void -convert_plane_hv (GstVideoConverter * convert, - const GstVideoFrame * src, GstVideoFrame * dest, gint plane) -{ - gint i, tmp_in; - gint in_x, in_y, out_x, out_y, out_width, out_height; - GstVideoFormat format; - GstVideoScaler *h_scaler, *v_scaler; - ConverterAlloc *alloc; - gpointer *lines; - gint splane = convert->fsplane[plane]; - - in_x = convert->fin_x[splane]; - in_y = convert->fin_y[splane]; - out_x = convert->fout_x[plane]; - out_y = convert->fout_y[plane]; - out_width = convert->fout_width[plane]; - out_height = convert->fout_height[plane]; - format = convert->fformat[plane]; - alloc = convert->flines; - lines = convert->lineptr; - - h_scaler = convert->fh_scaler[plane]; - v_scaler = convert->fv_scaler[plane]; - - tmp_in = 0; - for (i = 0; i < out_height; i++) { - guint in, n_taps, j; - guint8 *s, *d; - - gst_video_scaler_get_coeff (v_scaler, i, &in, &n_taps); - - while (tmp_in < in) - tmp_in++; - while (tmp_in < in + n_taps) { - s = FRAME_GET_PLANE_LINE (src, splane, tmp_in + in_y); - gst_video_scaler_horizontal (h_scaler, format, - s + in_x, GET_TMP_LINE (alloc, tmp_in), 0, out_width); - tmp_in++; - } - for (j = 0; j < n_taps; j++) - lines[j] = GET_TMP_LINE (alloc, in + j); - - d = FRAME_GET_PLANE_LINE (dest, plane, i + out_y); - gst_video_scaler_vertical (v_scaler, format, lines, d + out_x, i, - out_width); - } -} - static void convert_plane_hv_double (GstVideoConverter * convert, const GstVideoFrame * src, GstVideoFrame * dest, gint plane) @@ -3619,6 +3497,37 @@ convert_plane_hv_halve (GstVideoConverter * convert, convert->fout_width[plane], convert->fout_height[plane]); } +static void +convert_plane_hv (GstVideoConverter * convert, + const GstVideoFrame * src, GstVideoFrame * dest, gint plane) +{ + gint in_x, in_y, out_x, out_y, out_width, out_height; + GstVideoFormat format; + GstVideoScaler *h_scaler, *v_scaler; + gint splane = convert->fsplane[plane]; + guint8 *s, *d; + + in_x = convert->fin_x[splane]; + in_y = convert->fin_y[splane]; + out_x = convert->fout_x[plane]; + out_y = convert->fout_y[plane]; + out_width = convert->fout_width[plane]; + out_height = convert->fout_height[plane]; + format = convert->fformat[plane]; + + h_scaler = convert->fh_scaler[plane]; + v_scaler = convert->fv_scaler[plane]; + + s = FRAME_GET_PLANE_LINE (src, splane, in_y); + s += in_x; + d = FRAME_GET_PLANE_LINE (dest, plane, out_y); + d += out_x; + + gst_video_scaler_2d (h_scaler, v_scaler, format, + s, FRAME_GET_PLANE_STRIDE (src, splane), + d, FRAME_GET_PLANE_STRIDE (dest, plane), 0, 0, out_width, out_height); +} + static void convert_scale_planes (GstVideoConverter * convert, const GstVideoFrame * src, GstVideoFrame * dest) @@ -3916,7 +3825,7 @@ setup_scale (GstVideoConverter * convert) convert->fconvert[i] = convert_plane_v_double; GST_DEBUG ("plane %d: vertical double", i); } else { - convert->fconvert[i] = convert_plane_v; + convert->fconvert[i] = convert_plane_hv; GST_DEBUG ("plane %d: vertical scale", i); need_v_scaler = TRUE; } @@ -3928,7 +3837,7 @@ setup_scale (GstVideoConverter * convert) convert->fconvert[i] = convert_plane_h_double; GST_DEBUG ("plane %d: horizontal double", i); } else { - convert->fconvert[i] = convert_plane_h; + convert->fconvert[i] = convert_plane_hv; GST_DEBUG ("plane %d: horizontal scale", i); need_h_scaler = TRUE; } @@ -3951,21 +3860,22 @@ setup_scale (GstVideoConverter * convert) convert->fh_scaler[i] = gst_video_scaler_new (i == 0 ? method : cr_method, GST_VIDEO_SCALER_FLAG_NONE, taps, iw, ow, config); - } + } else + convert->fh_scaler[i] = NULL; + if (need_v_scaler) { convert->fv_scaler[i] = gst_video_scaler_new (i == 0 ? method : cr_method, GST_VIDEO_SCALER_FLAG_NONE, taps, ih, oh, config); gst_video_scaler_get_coeff (convert->fv_scaler[i], 0, NULL, &n_taps); - } + } else + convert->fv_scaler[i] = NULL; + gst_structure_free (config); max_taps = MAX (max_taps, n_taps); convert->fformat[i] = get_scale_format (in_format, i); } } - convert->flines = - converter_alloc_new (stride, max_taps + BACKLOG, NULL, NULL); - convert->lineptr = g_malloc (sizeof (gpointer) * max_taps); return TRUE; } diff --git a/gst-libs/gst/video/video-scaler.c b/gst-libs/gst/video/video-scaler.c index a59ac4179c..2b4e5ce75d 100644 --- a/gst-libs/gst/video/video-scaler.c +++ b/gst-libs/gst/video/video-scaler.c @@ -68,8 +68,8 @@ struct _GstVideoScaler gint inc; gint tmpwidth; - guint32 *tmpline1; - guint32 *tmpline2; + gpointer tmpline1; + gpointer tmpline2; }; static void @@ -1042,7 +1042,7 @@ video_scale_v_ntap_u16 (GstVideoScaler * scale, else src_inc = 1; - temp = (gint32 *) scale->tmpline1; + temp = (gint32 *) scale->tmpline2; count = width * n_elems; video_orc_resample_v_multaps_u16 (temp, srcs[0], taps[0], count); @@ -1139,6 +1139,139 @@ gst_video_scaler_combine_packed_YUV (GstVideoScaler * y_scale, return scale; } +static gboolean +get_functions (GstVideoScaler * hscale, GstVideoScaler * vscale, + GstVideoFormat format, + GstVideoScalerHFunc * hfunc, GstVideoScalerVFunc * vfunc, + gint * n_elems, gint * width_mult) +{ + gint bits; + + *width_mult = 1; + + switch (format) { + case GST_VIDEO_FORMAT_GRAY8: + bits = 8; + *n_elems = 1; + break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + bits = 8; + *n_elems = 1; + *width_mult = 2; + break; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + bits = 8; + *n_elems = 3; + break; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + bits = 8; + *n_elems = 4; + break; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + bits = 16; + *n_elems = 4; + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + bits = 16; + *n_elems = 1; + break; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV16: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_NV24: + bits = 8; + *n_elems = 2; + break; + default: + return FALSE; + } + if (bits == 8) { + switch (hscale ? hscale->resampler.max_taps : 0) { + case 0: + break; + case 1: + if (*n_elems == 1) + *hfunc = video_scale_h_near_u8; + else if (*n_elems == 2) + *hfunc = video_scale_h_near_u16; + else if (*n_elems == 3) + *hfunc = video_scale_h_near_3u8; + else if (*n_elems == 4) + *hfunc = video_scale_h_near_u32; + break; + case 2: + if (*n_elems == 1 && *width_mult == 1) + *hfunc = video_scale_h_2tap_1u8; + else if (*n_elems == 4) + *hfunc = video_scale_h_2tap_4u8; + else + *hfunc = video_scale_h_ntap_u8; + break; + default: + *hfunc = video_scale_h_ntap_u8; + break; + } + switch (vscale ? vscale->resampler.max_taps : 0) { + case 0: + break; + case 1: + *vfunc = video_scale_v_near_u8; + break; + case 2: + *vfunc = video_scale_v_2tap_u8; + break; + case 4: + *vfunc = video_scale_v_4tap_u8; + break; + default: + *vfunc = video_scale_v_ntap_u8; + break; + } + } else if (bits == 16) { + switch (hscale ? hscale->resampler.max_taps : 0) { + case 0: + break; + case 1: + if (*n_elems == 1) + *hfunc = video_scale_h_near_u16; + else + *hfunc = video_scale_h_near_u64; + break; + default: + *hfunc = video_scale_h_ntap_u16; + break; + } + switch (vscale ? vscale->resampler.max_taps : 0) { + case 0: + break; + case 1: + *vfunc = video_scale_v_near_u16; + break; + case 2: + *vfunc = video_scale_v_2tap_u16; + break; + default: + *vfunc = video_scale_v_ntap_u16; + break; + } + } + return TRUE; +} + /** * gst_video_scaler_horizontal: * @scale: a #GstVideoScaler @@ -1155,7 +1288,7 @@ void gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format, gpointer src, gpointer dest, guint dest_offset, guint width) { - gint n_elems; + gint n_elems, mult; GstVideoScalerHFunc func; g_return_if_fail (scale != NULL); @@ -1163,112 +1296,11 @@ gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format, g_return_if_fail (dest != NULL); g_return_if_fail (dest_offset + width <= scale->resampler.out_size); - switch (format) { - case GST_VIDEO_FORMAT_GRAY8: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u8; - break; - case 2: - func = video_scale_h_2tap_1u8; - break; - default: - func = video_scale_h_ntap_u8; - break; - } - n_elems = 1; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u8; - break; - default: - func = video_scale_h_ntap_u8; - break; - } - n_elems = 1; - width *= 2; - break; - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_v308: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_3u8; - break; - default: - func = video_scale_h_ntap_u8; - break; - } - n_elems = 3; - break; - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u32; - break; - case 2: - func = video_scale_h_2tap_4u8; - break; - default: - func = video_scale_h_ntap_u8; - break; - } - n_elems = 4; - break; - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_AYUV64: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u64; - break; - default: - func = video_scale_h_ntap_u16; - break; - } - n_elems = 4; - break; - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV16: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_NV24: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u16; - n_elems = 1; - break; - default: - func = video_scale_h_ntap_u8; - n_elems = 2; - break; - } - break; - case GST_VIDEO_FORMAT_GRAY16_LE: - case GST_VIDEO_FORMAT_GRAY16_BE: - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_h_near_u16; - break; - default: - func = video_scale_h_ntap_u16; - break; - } - n_elems = 1; - break; - default: - goto no_func; - } + if (!get_functions (scale, NULL, format, &func, NULL, &n_elems, &mult)) + goto no_func; + + width *= mult; + if (scale->tmpwidth < width) realloc_tmplines (scale, n_elems, width); @@ -1278,7 +1310,6 @@ gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format, no_func: { GST_WARNING ("no scaler function for format"); - func = NULL; } } @@ -1300,7 +1331,7 @@ void gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format, gpointer src_lines[], gpointer dest, guint dest_offset, guint width) { - gint n_elems, bits; + gint n_elems, mult; GstVideoScalerVFunc func; g_return_if_fail (scale != NULL); @@ -1308,87 +1339,10 @@ gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format, g_return_if_fail (dest != NULL); g_return_if_fail (dest_offset < scale->resampler.out_size); - switch (format) { - case GST_VIDEO_FORMAT_GRAY8: - bits = 8; - n_elems = 1; - break; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - bits = 8; - n_elems = 1; - width *= 2; - break; - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_v308: - bits = 8; - n_elems = 3; - break; - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - bits = 8; - n_elems = 4; - break; - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_AYUV64: - bits = 16; - n_elems = 4; - break; - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV16: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_NV24: - bits = 8; - n_elems = 2; - break; - case GST_VIDEO_FORMAT_GRAY16_LE: - case GST_VIDEO_FORMAT_GRAY16_BE: - bits = 16; - n_elems = 1; - break; - default: - goto no_func; - } - if (bits == 8) { - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_v_near_u8; - break; - case 2: - func = video_scale_v_2tap_u8; - break; - case 4: - func = video_scale_v_4tap_u8; - break; - default: - func = video_scale_v_ntap_u8; - break; - } - } else if (bits == 16) { - switch (scale->resampler.max_taps) { - case 1: - func = video_scale_v_near_u16; - break; - case 2: - func = video_scale_v_2tap_u16; - break; - default: - func = video_scale_v_ntap_u16; - break; - } - } else { - g_return_if_reached (); - func = NULL; - } + if (!get_functions (NULL, scale, format, NULL, &func, &n_elems, &mult)) + goto no_func; + + width *= mult; if (scale->tmpwidth < width) realloc_tmplines (scale, n_elems, width); @@ -1399,6 +1353,116 @@ gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format, no_func: { GST_WARNING ("no scaler function for format"); - func = NULL; + } +} + + +/** + * gst_video_scaler_2d: + * @hscale: a horzontal #GstVideoScaler + * @vscale: a vertical #GstVideoScaler + * @format: a #GstVideoFormat for @srcs and @dest + * @src: source pixels + * @src_stride: source pixels stride + * @dest: destination pixels + * @dest_stride: sinationource pixels stride + * @x: the horizontal destination offset + * @y: the vertical destination offset + * @width: the number of pixels to scale + * @height: the number of lines to scale + * + * Scale a rectangle of pixels in @src with @src_stride to @dest with + * @dest_stride using the horizontal scaler @hscaler and the vertical + * scaler @vscale. + * + * One of @hscale and @vscale can be NULL to only perform scaling in + * one dimension. + * + * @x and @y are the coordinates in the destination image to process. + */ +void +gst_video_scaler_2d (GstVideoScaler * hscale, GstVideoScaler * vscale, + GstVideoFormat format, gpointer src, gint src_stride, + gpointer dest, gint dest_stride, guint x, guint y, + guint width, guint height) +{ + gint n_elems, mult; + GstVideoScalerHFunc hfunc; + GstVideoScalerVFunc vfunc; + gint i; + + g_return_if_fail (hscale != NULL || vscale != NULL); + g_return_if_fail (src != NULL); + g_return_if_fail (dest != NULL); + + if (!get_functions (hscale, vscale, format, &hfunc, &vfunc, &n_elems, &mult)) + goto no_func; + + width *= mult; + +#define LINE(s,ss,i) ((guint8 *)(s) + ((i) * (ss))) +#define TMP_LINE(s,i,v) ((guint8 *)(s->tmpline1) + (((i) % (v)) * (sizeof (gint32) * width * n_elems))) + + if (vscale == NULL) { + if (hscale->tmpwidth < width) + realloc_tmplines (hscale, n_elems, width); + + /* only horizontal scaling */ + for (i = y; i < height; i++) { + hfunc (hscale, LINE (src, src_stride, i), LINE (dest, dest_stride, i), + x, width, n_elems); + } + } else { + guint v_taps; + gpointer *lines; + + if (vscale->tmpwidth < width) + realloc_tmplines (vscale, n_elems, width); + + v_taps = vscale->resampler.max_taps; + lines = g_alloca (v_taps * sizeof (gpointer)); + + if (hscale == NULL) { + /* only vertical scaling */ + for (i = y; i < height; i++) { + guint in, j; + + in = vscale->resampler.offset[i]; + for (j = 0; j < v_taps; j++) + lines[j] = LINE (src, src_stride, in + j); + + vfunc (vscale, lines, LINE (dest, dest_stride, i), i, width, n_elems); + } + } else { + gint tmp_in = y; + + if (hscale->tmpwidth < width) + realloc_tmplines (hscale, n_elems, width); + + /* horizontal and vertical scaling FIXME, we could probably do better + * by swapping horizontal or vertical scaling in some cases */ + for (i = y; i < height; i++) { + guint in, j; + + in = vscale->resampler.offset[i]; + while (tmp_in < in) + tmp_in++; + while (tmp_in < in + v_taps) { + hfunc (hscale, LINE (src, src_stride, tmp_in), TMP_LINE (vscale, + tmp_in, v_taps), x, width, n_elems); + tmp_in++; + } + for (j = 0; j < v_taps; j++) + lines[j] = TMP_LINE (vscale, in + j, v_taps); + + vfunc (vscale, lines, LINE (dest, dest_stride, i), i, width, n_elems); + } + } + } + return; + +no_func: + { + GST_WARNING ("no scaler function for format"); } } diff --git a/gst-libs/gst/video/video-scaler.h b/gst-libs/gst/video/video-scaler.h index ffc6ff7f5b..891a49de02 100644 --- a/gst-libs/gst/video/video-scaler.h +++ b/gst-libs/gst/video/video-scaler.h @@ -76,6 +76,14 @@ GstVideoScaler * gst_video_scaler_combine_packed_YUV (GstVideoScaler * y_sc GstVideoFormat in_format, GstVideoFormat out_format); +void gst_video_scaler_2d (GstVideoScaler *hscale, + GstVideoScaler *vscale, + GstVideoFormat format, + gpointer src, gint src_stride, + gpointer dest, gint dest_stride, + guint x, guint y, + guint width, guint height); + G_END_DECLS #endif /* __GST_VIDEO_SCALER_H__ */ diff --git a/win32/common/libgstvideo.def b/win32/common/libgstvideo.def index 08e5f53ba2..fcf719470b 100644 --- a/win32/common/libgstvideo.def +++ b/win32/common/libgstvideo.def @@ -232,6 +232,7 @@ EXPORTS gst_video_resampler_flags_get_type gst_video_resampler_init gst_video_resampler_method_get_type + gst_video_scaler_2d gst_video_scaler_combine_packed_YUV gst_video_scaler_free gst_video_scaler_get_coeff