mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue