mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
video-converter: add generic planar scaler/converter
Add code to convert and scale between any planar format and use it in the fastpaths of some planare converters.
This commit is contained in:
parent
dc8181c12e
commit
2566675a78
1 changed files with 396 additions and 285 deletions
|
@ -133,6 +133,9 @@ typedef struct
|
|||
GDestroyNotify notify;
|
||||
} ConverterAlloc;
|
||||
|
||||
typedef void (*FastConvertFunc) (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane);
|
||||
|
||||
struct _GstVideoConverter
|
||||
{
|
||||
gint flags;
|
||||
|
@ -243,11 +246,20 @@ struct _GstVideoConverter
|
|||
GstVideoFrame *dest;
|
||||
|
||||
/* fastpath */
|
||||
GstVideoFormat fformat;
|
||||
GstVideoScaler *fh_scaler[4];
|
||||
GstVideoScaler *fv_scaler[4];
|
||||
ConverterAlloc *flines;
|
||||
gpointer *lineptr;
|
||||
|
||||
GstVideoFormat fformat[4];
|
||||
gint fin_x[4];
|
||||
gint fin_y[4];
|
||||
gint fout_x[4];
|
||||
gint fout_y[4];
|
||||
gint fout_width[4];
|
||||
gint fout_height[4];
|
||||
gint fsplane[4];
|
||||
GstVideoScaler *fh_scaler[4];
|
||||
GstVideoScaler *fv_scaler[4];
|
||||
FastConvertFunc fconvert[4];
|
||||
};
|
||||
|
||||
typedef gpointer (*GstLineCacheAllocLineFunc) (GstLineCache * cache, gint idx,
|
||||
|
@ -2580,56 +2592,6 @@ convert_I420_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_I420_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
|
||||
video_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
|
||||
FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
|
||||
FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_420_422 (FRAME_GET_U_LINE (dest, 0),
|
||||
2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
|
||||
2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
|
||||
FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
|
||||
video_orc_planar_chroma_420_422 (FRAME_GET_V_LINE (dest, 0),
|
||||
2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
|
||||
2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
|
||||
FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_I420_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
|
||||
video_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
|
||||
FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
|
||||
FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_420_444 (FRAME_GET_U_LINE (dest, 0),
|
||||
2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (dest, 1),
|
||||
2 * FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
|
||||
FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
|
||||
video_orc_planar_chroma_420_444 (FRAME_GET_V_LINE (dest, 0),
|
||||
2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (dest, 1),
|
||||
2 * FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
|
||||
FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
|
||||
/* now handle last line */
|
||||
if (height & 1) {
|
||||
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_YUY2_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
|
@ -2978,70 +2940,6 @@ convert_AYUV_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
|
|||
convert_fill_border (convert, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y42B_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
|
||||
video_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
|
||||
FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
|
||||
FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_422_420 (FRAME_GET_U_LINE (dest, 0),
|
||||
FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
|
||||
2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
|
||||
2 * FRAME_GET_U_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
|
||||
video_orc_planar_chroma_422_420 (FRAME_GET_V_LINE (dest, 0),
|
||||
FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
|
||||
2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
|
||||
2 * FRAME_GET_V_STRIDE (src), (width + 1) / 2, height / 2);
|
||||
|
||||
/* now handle last line */
|
||||
if (height & 1) {
|
||||
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y42B_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
guint8 *dy, *sy, *du, *su, *dv, *sv;
|
||||
|
||||
sy = FRAME_GET_Y_LINE (src, convert->in_y);
|
||||
sy += convert->in_x;
|
||||
su = FRAME_GET_U_LINE (src, convert->in_y);
|
||||
su += convert->in_x >> 1;
|
||||
sv = FRAME_GET_V_LINE (src, convert->in_y);
|
||||
sv += convert->in_x >> 1;
|
||||
|
||||
dy = FRAME_GET_Y_LINE (dest, convert->out_y);
|
||||
dy += convert->out_x;
|
||||
du = FRAME_GET_U_LINE (dest, convert->out_y);
|
||||
du += convert->out_x;
|
||||
dv = FRAME_GET_V_LINE (dest, convert->out_y);
|
||||
dv += convert->out_x;
|
||||
|
||||
video_orc_memcpy_2d (dy, FRAME_GET_Y_STRIDE (dest), sy,
|
||||
FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_422_444 (du,
|
||||
FRAME_GET_U_STRIDE (dest), su,
|
||||
FRAME_GET_U_STRIDE (src), (width + 1) / 2, height);
|
||||
|
||||
video_orc_planar_chroma_422_444 (dv,
|
||||
FRAME_GET_V_STRIDE (dest), sv,
|
||||
FRAME_GET_V_STRIDE (src), (width + 1) / 2, height);
|
||||
|
||||
convert_fill_border (convert, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y42B_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
|
@ -3124,70 +3022,6 @@ convert_Y42B_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
|
|||
convert_fill_border (convert, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y444_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
|
||||
video_orc_memcpy_2d (FRAME_GET_Y_LINE (dest, 0),
|
||||
FRAME_GET_Y_STRIDE (dest), FRAME_GET_Y_LINE (src, 0),
|
||||
FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_444_420 (FRAME_GET_U_LINE (dest, 0),
|
||||
FRAME_GET_U_STRIDE (dest), FRAME_GET_U_LINE (src, 0),
|
||||
2 * FRAME_GET_U_STRIDE (src), FRAME_GET_U_LINE (src, 1),
|
||||
2 * FRAME_GET_U_STRIDE (src), width / 2, height / 2);
|
||||
|
||||
video_orc_planar_chroma_444_420 (FRAME_GET_V_LINE (dest, 0),
|
||||
FRAME_GET_V_STRIDE (dest), FRAME_GET_V_LINE (src, 0),
|
||||
2 * FRAME_GET_V_STRIDE (src), FRAME_GET_V_LINE (src, 1),
|
||||
2 * FRAME_GET_V_STRIDE (src), width / 2, height / 2);
|
||||
|
||||
/* now handle last line */
|
||||
if (height & 1) {
|
||||
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y444_Y42B (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
{
|
||||
gint width = convert->in_width;
|
||||
gint height = convert->in_height;
|
||||
guint8 *sy, *su, *sv, *dy, *du, *dv;
|
||||
|
||||
sy = FRAME_GET_Y_LINE (src, convert->in_y);
|
||||
sy += convert->in_x;
|
||||
su = FRAME_GET_U_LINE (src, convert->in_y);
|
||||
su += convert->in_x;
|
||||
sv = FRAME_GET_V_LINE (src, convert->in_y);
|
||||
sv += convert->in_x;
|
||||
|
||||
dy = FRAME_GET_Y_LINE (dest, convert->out_y);
|
||||
dy += convert->out_x;
|
||||
du = FRAME_GET_U_LINE (dest, convert->out_y);
|
||||
du += convert->out_x >> 1;
|
||||
dv = FRAME_GET_V_LINE (dest, convert->out_y);
|
||||
dv += convert->out_x >> 1;
|
||||
|
||||
video_orc_memcpy_2d (dy,
|
||||
FRAME_GET_Y_STRIDE (dest), sy, FRAME_GET_Y_STRIDE (src), width, height);
|
||||
|
||||
video_orc_planar_chroma_444_422 (du,
|
||||
FRAME_GET_U_STRIDE (dest), su,
|
||||
FRAME_GET_U_STRIDE (src), width / 2, height);
|
||||
|
||||
video_orc_planar_chroma_444_422 (dv,
|
||||
FRAME_GET_V_STRIDE (dest), sv,
|
||||
FRAME_GET_V_STRIDE (src), width / 2, height);
|
||||
|
||||
convert_fill_border (convert, dest);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_Y444_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||
GstVideoFrame * dest)
|
||||
|
@ -3507,67 +3341,265 @@ convert_fill_border (GstVideoConverter * convert, GstVideoFrame * dest)
|
|||
|
||||
#define GET_TMP_LINE(fl,idx) &fl->data[fl->stride * ((idx) % fl->n_lines)]
|
||||
|
||||
static void
|
||||
convert_plane_copy (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
||||
{
|
||||
guint8 *s, *d;
|
||||
gint splane = convert->fsplane[plane];
|
||||
|
||||
s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s += convert->fin_x[splane];
|
||||
d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d += convert->fout_x[plane];
|
||||
|
||||
video_orc_memcpy_2d (d, FRAME_GET_PLANE_STRIDE (dest, plane),
|
||||
s, FRAME_GET_PLANE_STRIDE (src, splane),
|
||||
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;
|
||||
GstFormat 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)
|
||||
{
|
||||
guint8 *s, *d;
|
||||
gint splane = convert->fsplane[plane];
|
||||
|
||||
s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s += convert->fin_x[splane];
|
||||
d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d += convert->fout_x[plane];
|
||||
|
||||
video_orc_planar_chroma_422_444 (d,
|
||||
FRAME_GET_PLANE_STRIDE (dest, plane), s,
|
||||
FRAME_GET_PLANE_STRIDE (src, splane), convert->fout_width[plane] / 2,
|
||||
convert->fout_height[plane]);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_plane_h_halve (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
||||
{
|
||||
guint8 *s, *d;
|
||||
gint splane = convert->fsplane[plane];
|
||||
|
||||
s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s += convert->fin_x[splane];
|
||||
d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d += convert->fout_x[plane];
|
||||
|
||||
video_orc_planar_chroma_444_422 (d,
|
||||
FRAME_GET_PLANE_STRIDE (dest, plane), s,
|
||||
FRAME_GET_PLANE_STRIDE (src, splane), convert->fout_width[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;
|
||||
GstFormat 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)
|
||||
{
|
||||
guint8 *s, *d1, *d2;
|
||||
gint ds, splane = convert->fsplane[plane];
|
||||
|
||||
s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s += convert->fin_x[splane];
|
||||
d1 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d1 += convert->fout_x[plane];
|
||||
d2 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane] + 1);
|
||||
d2 += convert->fout_x[plane];
|
||||
ds = FRAME_GET_PLANE_STRIDE (dest, plane);
|
||||
|
||||
video_orc_planar_chroma_420_422 (d1, 2 * ds, d2, 2 * ds,
|
||||
s, FRAME_GET_PLANE_STRIDE (src, splane), convert->fout_width[plane],
|
||||
convert->fout_height[plane] / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_plane_v_halve (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
||||
{
|
||||
guint8 *s1, *s2, *d;
|
||||
gint ss, ds, splane = convert->fsplane[plane];
|
||||
|
||||
s1 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s1 += convert->fin_x[splane];
|
||||
s2 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane] + 1);
|
||||
s2 += convert->fin_x[splane];
|
||||
d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d += convert->fout_x[plane];
|
||||
|
||||
ss = FRAME_GET_PLANE_STRIDE (src, splane);
|
||||
ds = FRAME_GET_PLANE_STRIDE (dest, plane);
|
||||
|
||||
video_orc_planar_chroma_422_420 (d, ds, s1, 2 * ss, s2, 2 * ss,
|
||||
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;
|
||||
GstFormat 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)
|
||||
{
|
||||
guint8 *s, *d1, *d2;
|
||||
gint ss, ds, splane = convert->fsplane[plane];
|
||||
|
||||
s = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s += convert->fin_x[splane];
|
||||
d1 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d1 += convert->fout_x[plane];
|
||||
d2 = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane] + 1);
|
||||
d2 += convert->fout_x[plane];
|
||||
ss = FRAME_GET_PLANE_STRIDE (src, splane);
|
||||
ds = FRAME_GET_PLANE_STRIDE (dest, plane);
|
||||
|
||||
video_orc_planar_chroma_420_444 (d1, 2 * ds, d2, 2 * ds, s, ss,
|
||||
(convert->fout_width[plane] + 1) / 2, convert->fout_height[plane] / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_plane_hv_halve (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest, gint plane)
|
||||
{
|
||||
guint8 *s1, *s2, *d;
|
||||
gint ss, ds, splane = convert->fsplane[plane];
|
||||
|
||||
s1 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane]);
|
||||
s1 += convert->fin_x[splane];
|
||||
s2 = FRAME_GET_PLANE_LINE (src, splane, convert->fin_y[splane] + 1);
|
||||
s2 += convert->fin_x[splane];
|
||||
d = FRAME_GET_PLANE_LINE (dest, plane, convert->fout_y[plane]);
|
||||
d += convert->fout_x[plane];
|
||||
ss = FRAME_GET_PLANE_STRIDE (src, splane);
|
||||
ds = FRAME_GET_PLANE_STRIDE (dest, plane);
|
||||
|
||||
video_orc_planar_chroma_444_420 (d, ds, s1, 2 * ss, s2, 2 * ss,
|
||||
convert->fout_width[plane], convert->fout_height[plane]);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_scale_planes (GstVideoConverter * convert,
|
||||
const GstVideoFrame * src, GstVideoFrame * dest)
|
||||
{
|
||||
int k, n_planes;
|
||||
GstVideoFormat format = convert->fformat;
|
||||
const GstVideoFormatInfo *in_finfo, *out_finfo;
|
||||
gpointer *lines = convert->lineptr;
|
||||
int i, n_planes;
|
||||
|
||||
in_finfo = convert->in_info.finfo;
|
||||
out_finfo = convert->out_info.finfo;
|
||||
|
||||
n_planes = GST_VIDEO_FRAME_N_PLANES (src);
|
||||
|
||||
for (k = 0; k < n_planes; k++) {
|
||||
gint i, tmp_in, in_x, in_y, out_x, out_y, out_width, out_height, pstride;
|
||||
GstVideoScaler *v_scaler, *h_scaler;
|
||||
ConverterAlloc *alloc;
|
||||
|
||||
v_scaler = convert->fv_scaler[k];
|
||||
h_scaler = convert->fh_scaler[k];
|
||||
|
||||
alloc = convert->flines;
|
||||
|
||||
/* FIXME. assumes subsampling of component N is the same as plane N, which is
|
||||
* currently true for all formats we have but it might not be in the future. */
|
||||
in_x = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, k, convert->in_x);
|
||||
in_y = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, k, convert->in_y);
|
||||
out_x = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, k, convert->out_x);
|
||||
out_y = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, k, convert->out_y);
|
||||
out_width =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, k, convert->out_width);
|
||||
out_height =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, k, convert->out_height);
|
||||
|
||||
pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, k);
|
||||
in_x *= pstride;
|
||||
out_x *= pstride;
|
||||
|
||||
tmp_in = 0;
|
||||
for (i = 0; i < out_height; i++) {
|
||||
guint8 *d, *s;
|
||||
guint in, n_taps, j;
|
||||
|
||||
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, k, 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, k, i + out_y);
|
||||
gst_video_scaler_vertical (v_scaler, format, lines, d + out_x, i,
|
||||
out_width);
|
||||
}
|
||||
n_planes = GST_VIDEO_FRAME_N_PLANES (dest);
|
||||
for (i = 0; i < n_planes; i++) {
|
||||
convert->fconvert[i] (convert, src, dest, i);
|
||||
}
|
||||
convert_fill_border (convert, dest);
|
||||
}
|
||||
|
@ -3576,7 +3608,7 @@ static gboolean
|
|||
setup_scale (GstVideoConverter * convert, GstVideoFormat fformat)
|
||||
{
|
||||
int i, n_planes;
|
||||
gint method, stride = 0, in_w, in_h, out_w, out_h;
|
||||
gint method, stride = 0, in_width, in_height, out_width, out_height;
|
||||
guint taps, max_taps = 0;
|
||||
GstVideoInfo *in_info, *out_info;
|
||||
const GstVideoFormatInfo *in_finfo, *out_finfo;
|
||||
|
@ -3604,24 +3636,24 @@ setup_scale (GstVideoConverter * convert, GstVideoFormat fformat)
|
|||
break;
|
||||
}
|
||||
|
||||
in_w = convert->in_width;
|
||||
in_h = convert->in_height;
|
||||
out_w = convert->out_width;
|
||||
out_h = convert->out_height;
|
||||
in_width = convert->in_width;
|
||||
in_height = convert->in_height;
|
||||
out_width = convert->out_width;
|
||||
out_height = convert->out_height;
|
||||
|
||||
if (n_planes == 1) {
|
||||
if (GST_VIDEO_INFO_IS_YUV (in_info)) {
|
||||
GstVideoScaler *y_scaler, *uv_scaler;
|
||||
|
||||
y_scaler = gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_Y, in_w),
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, GST_VIDEO_COMP_Y,
|
||||
out_w), convert->config);
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_Y,
|
||||
in_width), GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo,
|
||||
GST_VIDEO_COMP_Y, out_width), convert->config);
|
||||
uv_scaler =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_U, in_w),
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, GST_VIDEO_COMP_U,
|
||||
out_w), convert->config);
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, GST_VIDEO_COMP_U,
|
||||
in_width), GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo,
|
||||
GST_VIDEO_COMP_U, out_width), convert->config);
|
||||
|
||||
convert->fh_scaler[0] =
|
||||
gst_video_scaler_combine_packed_YUV (y_scaler, uv_scaler,
|
||||
|
@ -3632,39 +3664,117 @@ setup_scale (GstVideoConverter * convert, GstVideoFormat fformat)
|
|||
} else {
|
||||
convert->fh_scaler[0] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
in_w, out_w, convert->config);
|
||||
in_width, out_width, convert->config);
|
||||
}
|
||||
stride = MAX (stride, GST_VIDEO_INFO_PLANE_STRIDE (in_info, 0));
|
||||
stride = MAX (stride, GST_VIDEO_INFO_PLANE_STRIDE (out_info, 0));
|
||||
|
||||
convert->fv_scaler[0] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
in_h, out_h, convert->config);
|
||||
in_height, out_height, convert->config);
|
||||
|
||||
gst_video_scaler_get_coeff (convert->fv_scaler[0], 0, NULL, &max_taps);
|
||||
convert->fformat = fformat;
|
||||
|
||||
convert->fconvert[0] = convert_plane_hv;
|
||||
convert->fformat[0] = fformat;
|
||||
convert->fsplane[0] = 0;
|
||||
} else {
|
||||
for (i = 0; i < n_planes; i++) {
|
||||
guint n_taps;
|
||||
guint n_taps = 0;
|
||||
gint j, iw, ih, ow, oh, pstride;
|
||||
gboolean need_v_scaler, need_h_scaler;
|
||||
|
||||
/* find the component in this plane and map it to the plane of
|
||||
* the source */
|
||||
for (j = 0; i < GST_VIDEO_MAX_COMPONENTS; j++) {
|
||||
if (GST_VIDEO_FORMAT_INFO_PLANE (out_finfo, j) == i) {
|
||||
convert->fsplane[i] = GST_VIDEO_FORMAT_INFO_PLANE (in_finfo, j);
|
||||
GST_DEBUG ("plane %d -> %d", i, convert->fsplane[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stride = MAX (stride, GST_VIDEO_INFO_COMP_STRIDE (in_info, i));
|
||||
stride = MAX (stride, GST_VIDEO_INFO_COMP_STRIDE (out_info, i));
|
||||
|
||||
convert->fh_scaler[i] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, i, in_w),
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, i, out_w),
|
||||
convert->config);
|
||||
convert->fv_scaler[i] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, i, in_h),
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, i, out_h),
|
||||
convert->config);
|
||||
iw = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, i, in_width);
|
||||
ih = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, i, in_height);
|
||||
ow = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, i, out_width);
|
||||
oh = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, i, out_height);
|
||||
|
||||
gst_video_scaler_get_coeff (convert->fv_scaler[i], 0, NULL, &n_taps);
|
||||
convert->fout_width[i] = ow;
|
||||
convert->fout_height[i] = oh;
|
||||
|
||||
pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (out_finfo, i);
|
||||
convert->fin_x[i] =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (in_finfo, i, convert->in_x);
|
||||
convert->fin_x[i] *= pstride;
|
||||
convert->fin_y[i] =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (in_finfo, i, convert->in_y);
|
||||
convert->fout_x[i] =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (out_finfo, i, convert->out_x);
|
||||
convert->fout_x[i] *= pstride;
|
||||
convert->fout_y[i] =
|
||||
GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (out_finfo, i, convert->out_y);
|
||||
|
||||
need_v_scaler = FALSE;
|
||||
need_h_scaler = FALSE;
|
||||
if (iw == ow) {
|
||||
if (ih == oh) {
|
||||
convert->fconvert[i] = convert_plane_copy;
|
||||
GST_DEBUG ("plane %d: copy", i);
|
||||
} else if (ih == 2 * oh) {
|
||||
convert->fconvert[i] = convert_plane_v_halve;
|
||||
GST_DEBUG ("plane %d: vertical halve", i);
|
||||
} else if (2 * ih == oh) {
|
||||
convert->fconvert[i] = convert_plane_v_double;
|
||||
GST_DEBUG ("plane %d: vertical double", i);
|
||||
} else {
|
||||
convert->fconvert[i] = convert_plane_v;
|
||||
GST_DEBUG ("plane %d: vertical scale", i);
|
||||
need_v_scaler = TRUE;
|
||||
}
|
||||
} else if (ih == oh) {
|
||||
if (iw == 2 * ow) {
|
||||
convert->fconvert[i] = convert_plane_h_halve;
|
||||
GST_DEBUG ("plane %d: horizontal halve", i);
|
||||
} else if (2 * iw == ow) {
|
||||
convert->fconvert[i] = convert_plane_h_double;
|
||||
GST_DEBUG ("plane %d: horizontal double", i);
|
||||
} else {
|
||||
convert->fconvert[i] = convert_plane_h;
|
||||
GST_DEBUG ("plane %d: horizontal scale", i);
|
||||
need_h_scaler = TRUE;
|
||||
}
|
||||
} else {
|
||||
if (iw == 2 * ow && ih == 2 * oh) {
|
||||
convert->fconvert[i] = convert_plane_hv_halve;
|
||||
GST_DEBUG ("plane %d: horizontal/vertical halve", i);
|
||||
} else if (2 * iw == ow && 2 * ih == oh) {
|
||||
convert->fconvert[i] = convert_plane_hv_double;
|
||||
GST_DEBUG ("plane %d: horizontal/vertical double", i);
|
||||
} else {
|
||||
convert->fconvert[i] = convert_plane_hv;
|
||||
GST_DEBUG ("plane %d: horizontal/vertical scale", i);
|
||||
need_v_scaler = TRUE;
|
||||
need_h_scaler = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_h_scaler) {
|
||||
convert->fh_scaler[i] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
iw, ow, convert->config);
|
||||
}
|
||||
if (need_v_scaler) {
|
||||
convert->fv_scaler[i] =
|
||||
gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
|
||||
ih, oh, convert->config);
|
||||
gst_video_scaler_get_coeff (convert->fv_scaler[i], 0, NULL, &n_taps);
|
||||
}
|
||||
max_taps = MAX (max_taps, n_taps);
|
||||
convert->fformat[i] = fformat;
|
||||
}
|
||||
convert->fformat = fformat;
|
||||
}
|
||||
convert->flines =
|
||||
converter_alloc_new (stride, max_taps + BACKLOG, NULL, NULL);
|
||||
|
@ -3697,10 +3807,11 @@ static const VideoTransform transforms[] = {
|
|||
FALSE, 0, 0, convert_I420_UYVY},
|
||||
{GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_AYUV},
|
||||
{GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_Y42B},
|
||||
{GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_Y444},
|
||||
|
||||
{GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_YUY2},
|
||||
|
@ -3708,10 +3819,10 @@ static const VideoTransform transforms[] = {
|
|||
FALSE, 0, 0, convert_I420_UYVY},
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_AYUV},
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_Y42B},
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_I420_Y444},
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y42B, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_Y444, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
|
||||
{GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_I420, TRUE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_YUY2_I420},
|
||||
|
@ -3752,31 +3863,31 @@ static const VideoTransform transforms[] = {
|
|||
{GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 0, 0, convert_AYUV_Y444},
|
||||
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_I420, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_Y42B_I420},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 0, 0, convert_Y42B_I420},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 0, 0, convert_Y42B_YUY2},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 0, 0, convert_Y42B_UYVY},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 1, 0, convert_Y42B_AYUV},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 0, 0, convert_Y42B_Y444},
|
||||
{GST_VIDEO_FORMAT_Y42B, GST_VIDEO_FORMAT_Y444, TRUE, FALSE, FALSE, TRUE,
|
||||
TRUE, 0, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_I420, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 1, 0, convert_Y444_I420},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, TRUE, FALSE,
|
||||
FALSE, 1, 0, convert_Y444_I420},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_I420, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 1, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YV12, FALSE, FALSE, FALSE, TRUE,
|
||||
TRUE, 1, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_YUY2, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 1, 0, convert_Y444_YUY2},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_UYVY, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 1, 0, convert_Y444_UYVY},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_AYUV, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 0, 0, convert_Y444_AYUV},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, TRUE, TRUE,
|
||||
TRUE, 1, 0, convert_Y444_Y42B},
|
||||
{GST_VIDEO_FORMAT_Y444, GST_VIDEO_FORMAT_Y42B, TRUE, FALSE, FALSE, TRUE,
|
||||
TRUE, 1, 0, convert_scale_planes, GST_VIDEO_FORMAT_GRAY8},
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
{GST_VIDEO_FORMAT_AYUV, GST_VIDEO_FORMAT_ARGB, TRUE, TRUE, TRUE, TRUE, TRUE,
|
||||
|
@ -3949,7 +4060,7 @@ video_converter_lookup_fastpath (GstVideoConverter * convert)
|
|||
transforms[i].out_format == out_format &&
|
||||
(transforms[i].keeps_interlaced || !interlaced) &&
|
||||
(transforms[i].needs_color_matrix || (same_matrix && same_primaries))
|
||||
&& (transforms[i].keeps_size || !same_size)
|
||||
&& (!transforms[i].keeps_size || same_size)
|
||||
&& (transforms[i].width_align & width) == 0
|
||||
&& (transforms[i].height_align & height) == 0
|
||||
&& (transforms[i].do_crop || !crop)
|
||||
|
|
Loading…
Reference in a new issue