mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-18 12:15:19 +00:00
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.
This commit is contained in:
parent
80249d4bea
commit
cdd86d025a
4 changed files with 306 additions and 323 deletions
|
@ -246,9 +246,6 @@ struct _GstVideoConverter
|
||||||
GstVideoFrame *dest;
|
GstVideoFrame *dest;
|
||||||
|
|
||||||
/* fastpath */
|
/* fastpath */
|
||||||
ConverterAlloc *flines;
|
|
||||||
gpointer *lineptr;
|
|
||||||
|
|
||||||
GstVideoFormat fformat[4];
|
GstVideoFormat fformat[4];
|
||||||
gint fin_x[4];
|
gint fin_x[4];
|
||||||
gint fin_y[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->gamma_enc.gamma_table);
|
||||||
|
|
||||||
g_free (convert->tmpline);
|
g_free (convert->tmpline);
|
||||||
g_free (convert->lineptr);
|
|
||||||
g_free (convert->borderline);
|
g_free (convert->borderline);
|
||||||
|
|
||||||
if (convert->config)
|
if (convert->config)
|
||||||
|
@ -1959,8 +1955,6 @@ gst_video_converter_free (GstVideoConverter * convert)
|
||||||
if (convert->fh_scaler[i])
|
if (convert->fh_scaler[i])
|
||||||
gst_video_scaler_free (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);
|
g_slice_free (GstVideoConverter, convert);
|
||||||
}
|
}
|
||||||
|
@ -3386,35 +3380,6 @@ convert_plane_copy (GstVideoConverter * convert,
|
||||||
convert->fout_width[plane], convert->fout_height[plane]);
|
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
|
static void
|
||||||
convert_plane_h_double (GstVideoConverter * convert,
|
convert_plane_h_double (GstVideoConverter * convert,
|
||||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
||||||
|
@ -3451,44 +3416,6 @@ convert_plane_h_halve (GstVideoConverter * convert,
|
||||||
convert->fout_height[plane]);
|
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
|
static void
|
||||||
convert_plane_v_double (GstVideoConverter * convert,
|
convert_plane_v_double (GstVideoConverter * convert,
|
||||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
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]);
|
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
|
static void
|
||||||
convert_plane_hv_double (GstVideoConverter * convert,
|
convert_plane_hv_double (GstVideoConverter * convert,
|
||||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
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]);
|
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
|
static void
|
||||||
convert_scale_planes (GstVideoConverter * convert,
|
convert_scale_planes (GstVideoConverter * convert,
|
||||||
const GstVideoFrame * src, GstVideoFrame * dest)
|
const GstVideoFrame * src, GstVideoFrame * dest)
|
||||||
|
@ -3916,7 +3825,7 @@ setup_scale (GstVideoConverter * convert)
|
||||||
convert->fconvert[i] = convert_plane_v_double;
|
convert->fconvert[i] = convert_plane_v_double;
|
||||||
GST_DEBUG ("plane %d: vertical double", i);
|
GST_DEBUG ("plane %d: vertical double", i);
|
||||||
} else {
|
} else {
|
||||||
convert->fconvert[i] = convert_plane_v;
|
convert->fconvert[i] = convert_plane_hv;
|
||||||
GST_DEBUG ("plane %d: vertical scale", i);
|
GST_DEBUG ("plane %d: vertical scale", i);
|
||||||
need_v_scaler = TRUE;
|
need_v_scaler = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3928,7 +3837,7 @@ setup_scale (GstVideoConverter * convert)
|
||||||
convert->fconvert[i] = convert_plane_h_double;
|
convert->fconvert[i] = convert_plane_h_double;
|
||||||
GST_DEBUG ("plane %d: horizontal double", i);
|
GST_DEBUG ("plane %d: horizontal double", i);
|
||||||
} else {
|
} else {
|
||||||
convert->fconvert[i] = convert_plane_h;
|
convert->fconvert[i] = convert_plane_hv;
|
||||||
GST_DEBUG ("plane %d: horizontal scale", i);
|
GST_DEBUG ("plane %d: horizontal scale", i);
|
||||||
need_h_scaler = TRUE;
|
need_h_scaler = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3951,21 +3860,22 @@ setup_scale (GstVideoConverter * convert)
|
||||||
convert->fh_scaler[i] =
|
convert->fh_scaler[i] =
|
||||||
gst_video_scaler_new (i == 0 ? method : cr_method,
|
gst_video_scaler_new (i == 0 ? method : cr_method,
|
||||||
GST_VIDEO_SCALER_FLAG_NONE, taps, iw, ow, config);
|
GST_VIDEO_SCALER_FLAG_NONE, taps, iw, ow, config);
|
||||||
}
|
} else
|
||||||
|
convert->fh_scaler[i] = NULL;
|
||||||
|
|
||||||
if (need_v_scaler) {
|
if (need_v_scaler) {
|
||||||
convert->fv_scaler[i] =
|
convert->fv_scaler[i] =
|
||||||
gst_video_scaler_new (i == 0 ? method : cr_method,
|
gst_video_scaler_new (i == 0 ? method : cr_method,
|
||||||
GST_VIDEO_SCALER_FLAG_NONE, taps, ih, oh, config);
|
GST_VIDEO_SCALER_FLAG_NONE, taps, ih, oh, config);
|
||||||
gst_video_scaler_get_coeff (convert->fv_scaler[i], 0, NULL, &n_taps);
|
gst_video_scaler_get_coeff (convert->fv_scaler[i], 0, NULL, &n_taps);
|
||||||
}
|
} else
|
||||||
|
convert->fv_scaler[i] = NULL;
|
||||||
|
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
max_taps = MAX (max_taps, n_taps);
|
max_taps = MAX (max_taps, n_taps);
|
||||||
convert->fformat[i] = get_scale_format (in_format, i);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,8 @@ struct _GstVideoScaler
|
||||||
gint inc;
|
gint inc;
|
||||||
|
|
||||||
gint tmpwidth;
|
gint tmpwidth;
|
||||||
guint32 *tmpline1;
|
gpointer tmpline1;
|
||||||
guint32 *tmpline2;
|
gpointer tmpline2;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1042,7 +1042,7 @@ video_scale_v_ntap_u16 (GstVideoScaler * scale,
|
||||||
else
|
else
|
||||||
src_inc = 1;
|
src_inc = 1;
|
||||||
|
|
||||||
temp = (gint32 *) scale->tmpline1;
|
temp = (gint32 *) scale->tmpline2;
|
||||||
count = width * n_elems;
|
count = width * n_elems;
|
||||||
|
|
||||||
video_orc_resample_v_multaps_u16 (temp, srcs[0], taps[0], count);
|
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;
|
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:
|
* gst_video_scaler_horizontal:
|
||||||
* @scale: a #GstVideoScaler
|
* @scale: a #GstVideoScaler
|
||||||
|
@ -1155,7 +1288,7 @@ void
|
||||||
gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format,
|
gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format,
|
||||||
gpointer src, gpointer dest, guint dest_offset, guint width)
|
gpointer src, gpointer dest, guint dest_offset, guint width)
|
||||||
{
|
{
|
||||||
gint n_elems;
|
gint n_elems, mult;
|
||||||
GstVideoScalerHFunc func;
|
GstVideoScalerHFunc func;
|
||||||
|
|
||||||
g_return_if_fail (scale != NULL);
|
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 != NULL);
|
||||||
g_return_if_fail (dest_offset + width <= scale->resampler.out_size);
|
g_return_if_fail (dest_offset + width <= scale->resampler.out_size);
|
||||||
|
|
||||||
switch (format) {
|
if (!get_functions (scale, NULL, format, &func, NULL, &n_elems, &mult))
|
||||||
case GST_VIDEO_FORMAT_GRAY8:
|
goto no_func;
|
||||||
switch (scale->resampler.max_taps) {
|
|
||||||
case 1:
|
width *= mult;
|
||||||
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 (scale->tmpwidth < width)
|
if (scale->tmpwidth < width)
|
||||||
realloc_tmplines (scale, n_elems, width);
|
realloc_tmplines (scale, n_elems, width);
|
||||||
|
|
||||||
|
@ -1278,7 +1310,6 @@ gst_video_scaler_horizontal (GstVideoScaler * scale, GstVideoFormat format,
|
||||||
no_func:
|
no_func:
|
||||||
{
|
{
|
||||||
GST_WARNING ("no scaler function for format");
|
GST_WARNING ("no scaler function for format");
|
||||||
func = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,7 +1331,7 @@ void
|
||||||
gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format,
|
gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format,
|
||||||
gpointer src_lines[], gpointer dest, guint dest_offset, guint width)
|
gpointer src_lines[], gpointer dest, guint dest_offset, guint width)
|
||||||
{
|
{
|
||||||
gint n_elems, bits;
|
gint n_elems, mult;
|
||||||
GstVideoScalerVFunc func;
|
GstVideoScalerVFunc func;
|
||||||
|
|
||||||
g_return_if_fail (scale != NULL);
|
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 != NULL);
|
||||||
g_return_if_fail (dest_offset < scale->resampler.out_size);
|
g_return_if_fail (dest_offset < scale->resampler.out_size);
|
||||||
|
|
||||||
switch (format) {
|
if (!get_functions (NULL, scale, format, NULL, &func, &n_elems, &mult))
|
||||||
case GST_VIDEO_FORMAT_GRAY8:
|
goto no_func;
|
||||||
bits = 8;
|
|
||||||
n_elems = 1;
|
width *= mult;
|
||||||
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 (scale->tmpwidth < width)
|
if (scale->tmpwidth < width)
|
||||||
realloc_tmplines (scale, n_elems, width);
|
realloc_tmplines (scale, n_elems, width);
|
||||||
|
@ -1399,6 +1353,116 @@ gst_video_scaler_vertical (GstVideoScaler * scale, GstVideoFormat format,
|
||||||
no_func:
|
no_func:
|
||||||
{
|
{
|
||||||
GST_WARNING ("no scaler function for format");
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,14 @@ GstVideoScaler * gst_video_scaler_combine_packed_YUV (GstVideoScaler * y_sc
|
||||||
GstVideoFormat in_format,
|
GstVideoFormat in_format,
|
||||||
GstVideoFormat out_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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_VIDEO_SCALER_H__ */
|
#endif /* __GST_VIDEO_SCALER_H__ */
|
||||||
|
|
|
@ -232,6 +232,7 @@ EXPORTS
|
||||||
gst_video_resampler_flags_get_type
|
gst_video_resampler_flags_get_type
|
||||||
gst_video_resampler_init
|
gst_video_resampler_init
|
||||||
gst_video_resampler_method_get_type
|
gst_video_resampler_method_get_type
|
||||||
|
gst_video_scaler_2d
|
||||||
gst_video_scaler_combine_packed_YUV
|
gst_video_scaler_combine_packed_YUV
|
||||||
gst_video_scaler_free
|
gst_video_scaler_free
|
||||||
gst_video_scaler_get_coeff
|
gst_video_scaler_get_coeff
|
||||||
|
|
Loading…
Reference in a new issue