cog: (re-)implement 1/2/4-tap scaling

This commit is contained in:
David Schleef 2009-09-21 09:35:30 -07:00
parent 213cc0b06d
commit 06c3d2e93c
3 changed files with 161 additions and 29 deletions

View file

@ -18,6 +18,7 @@ libgstcog_la_SOURCES = \
cog.h \ cog.h \
cogframe.c \ cogframe.c \
cogframe.h \ cogframe.h \
cogtables.c \
cogutils.h \ cogutils.h \
cogvirtframe.c \ cogvirtframe.c \
cogvirtframe.h \ cogvirtframe.h \
@ -32,6 +33,10 @@ libgstcog_la_SOURCES = \
gstcolorconvert.c \ gstcolorconvert.c \
gstlogoinsert.c gstlogoinsert.c
noinst_PROGRAMS = generate_tables
generate_tables_CFLAGS = $(GST_CFLAGS)
generate_tables_LDADD = $(GST_LIBS)
nodist_libgstcog_la_SOURCES = cogorc.c cogorc.h nodist_libgstcog_la_SOURCES = cogorc.c cogorc.h
CLEANFILES = cogorc.c cogorc.h CLEANFILES = cogorc.c cogorc.h

View file

@ -318,6 +318,24 @@ mergebw t2, s2, s3
mergewl d1, t1, t2 mergewl d1, t1, t2
.function cogorc_combine2_u8
.dest 1 d1
.source 1 s1
.source 1 s2
.param 2 p1
.param 2 p2
.temp 2 t1
.temp 2 t2
convubw t1, s1
mullw t1, t1, p1
convubw t2, s2
mullw t2, t2, p2
addw t1, t1, t2
shruw t1, t1, 8
convuuswb d1, t1
.function cogorc_combine4_u8 .function cogorc_combine4_u8
.dest 1 d1 .dest 1 d1
.source 1 s1 .source 1 s1

View file

@ -14,6 +14,7 @@
#include "cogorc.h" #include "cogorc.h"
extern gint8 cog_resample_table_4tap[256][4];
CogFrame * CogFrame *
cog_frame_new_virtual (CogMemoryDomain * domain, CogFrameFormat format, cog_frame_new_virtual (CogMemoryDomain * domain, CogFrameFormat format,
@ -499,17 +500,54 @@ cog_virt_frame_new_vert_downsample (CogFrame * vf, int n_taps)
} }
void void
get_taps (double *taps, double x) cog_virt_frame_render_resample_vert_1tap (CogFrame * frame, void *_dest,
int component, int i)
{ {
taps[3] = x * x * (x - 1); uint8_t *dest = _dest;
taps[2] = x * (-x * x + x + 1); uint8_t *src1;
x = 1 - x; int n_src;
taps[1] = x * (-x * x + x + 1); double *scale = (double *) frame->virt_priv;
taps[0] = x * x * (x - 1); double x;
int src_i;
x = (*scale) * i;
src_i = floor (x);
n_src = frame->virt_frame1->components[component].height;
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (src_i + 0, 0, n_src - 1));
orc_memcpy (dest, src1, frame->components[component].width);
} }
void void
cog_virt_frame_render_resample_vert (CogFrame * frame, void *_dest, cog_virt_frame_render_resample_vert_2tap (CogFrame * frame, void *_dest,
int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src1;
uint8_t *src2;
int n_src;
double *scale = (double *) frame->virt_priv;
double x;
int src_i;
x = (*scale) * i;
src_i = floor (x);
x -= floor (x);
n_src = frame->virt_frame1->components[component].height;
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (src_i + 0, 0, n_src - 1));
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
CLAMP (src_i + 1, 0, n_src - 1));
cogorc_combine2_u8 (dest, src1, src2,
rint (256 * (1 - x)), rint (256 * x), frame->components[component].width);
}
void
cog_virt_frame_render_resample_vert_4tap (CogFrame * frame, void *_dest,
int component, int i) int component, int i)
{ {
uint8_t *dest = _dest; uint8_t *dest = _dest;
@ -518,14 +556,14 @@ cog_virt_frame_render_resample_vert (CogFrame * frame, void *_dest,
uint8_t *src3; uint8_t *src3;
uint8_t *src4; uint8_t *src4;
int n_src; int n_src;
double taps[4];
double *scale = (double *) frame->virt_priv; double *scale = (double *) frame->virt_priv;
double x; double x;
int src_i; int src_i;
int y;
x = (*scale) * i; x = (*scale) * i;
src_i = floor (x); src_i = floor (x);
get_taps (taps, x - floor (x)); y = 256 * (x - floor (x));
n_src = frame->virt_frame1->components[component].height; n_src = frame->virt_frame1->components[component].height;
src1 = cog_virt_frame_get_line (frame->virt_frame1, component, src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
@ -538,9 +576,10 @@ cog_virt_frame_render_resample_vert (CogFrame * frame, void *_dest,
CLAMP (src_i + 2, 0, n_src - 1)); CLAMP (src_i + 2, 0, n_src - 1));
cogorc_combine4_u8 (dest, src1, src2, src3, src4, cogorc_combine4_u8 (dest, src1, src2, src3, src4,
rint (taps[0] * 64.0), rint (taps[1] * 64.0), cog_resample_table_4tap[y][0],
rint (taps[2] * 64.0), rint (taps[3] * 64.0), cog_resample_table_4tap[y][1],
frame->components[component].width); cog_resample_table_4tap[y][2],
cog_resample_table_4tap[y][3], frame->components[component].width);
} }
CogFrame * CogFrame *
@ -548,10 +587,17 @@ cog_virt_frame_new_vert_resample (CogFrame * vf, int height)
{ {
CogFrame *virt_frame; CogFrame *virt_frame;
double *scale; double *scale;
int taps = 4;
virt_frame = cog_frame_new_virtual (NULL, vf->format, vf->width, height); virt_frame = cog_frame_new_virtual (NULL, vf->format, vf->width, height);
virt_frame->virt_frame1 = vf; virt_frame->virt_frame1 = vf;
virt_frame->render_line = cog_virt_frame_render_resample_vert; if (taps == 1) {
virt_frame->render_line = cog_virt_frame_render_resample_vert_1tap;
} else if (taps == 2) {
virt_frame->render_line = cog_virt_frame_render_resample_vert_2tap;
} else {
virt_frame->render_line = cog_virt_frame_render_resample_vert_4tap;
}
scale = malloc (sizeof (double)); scale = malloc (sizeof (double));
virt_frame->virt_priv = scale; virt_frame->virt_priv = scale;
@ -562,34 +608,91 @@ cog_virt_frame_new_vert_resample (CogFrame * vf, int height)
} }
void void
cog_virt_frame_render_resample_horiz (CogFrame * frame, void *_dest, cog_virt_frame_render_resample_horiz_1tap (CogFrame * frame, void *_dest,
int component, int i) int component, int i)
{ {
uint8_t *dest = _dest; uint8_t *dest = _dest;
uint8_t *src; uint8_t *src;
int j; int j;
int n_src; int n_src;
double taps[4]; int scale = frame->param1;
double *scale = (double *) frame->virt_priv; int acc;
int src_i;
n_src = frame->virt_frame1->components[component].width; n_src = frame->virt_frame1->components[component].width;
src = cog_virt_frame_get_line (frame->virt_frame1, component, i); src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
acc = 0;
for (j = 0; j < frame->components[component].width; j++) { for (j = 0; j < frame->components[component].width; j++) {
double x; dest[j] = src[(acc >> 8)];
double y = 0; acc += scale;
}
}
x = (*scale) * j; void
src_i = floor (x); cog_virt_frame_render_resample_horiz_4tap (CogFrame * frame, void *_dest,
get_taps (taps, x - floor (x)); int component, int i)
{
uint8_t *dest = _dest;
uint8_t *src;
int j;
int n_src;
int scale = frame->param1;
int acc;
y = 0; n_src = frame->virt_frame1->components[component].width;
y += taps[0] * src[CLAMP (src_i - 1, 0, n_src - 1)]; src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
y += taps[1] * src[CLAMP (src_i + 0, 0, n_src - 1)];
y += taps[2] * src[CLAMP (src_i + 1, 0, n_src - 1)]; acc = 0;
y += taps[3] * src[CLAMP (src_i + 2, 0, n_src - 1)]; for (j = 0; j < 1; j++) {
dest[j] = CLAMP (rint (y), 0, 255); int src_i;
int y;
int z;
src_i = acc >> 8;
y = acc & 255;
z = 32;
z += cog_resample_table_4tap[y][0] * src[CLAMP (src_i - 1, 0, n_src - 1)];
z += cog_resample_table_4tap[y][1] * src[CLAMP (src_i + 0, 0, n_src - 1)];
z += cog_resample_table_4tap[y][2] * src[CLAMP (src_i + 1, 0, n_src - 1)];
z += cog_resample_table_4tap[y][3] * src[CLAMP (src_i + 2, 0, n_src - 1)];
z >>= 6;
dest[j] = CLAMP (z, 0, 255);
acc += scale;
}
for (; j < frame->components[component].width - 2; j++) {
int src_i;
int y;
int z;
src_i = acc >> 8;
y = acc & 255;
z = 32;
z += cog_resample_table_4tap[y][0] * src[src_i - 1];
z += cog_resample_table_4tap[y][1] * src[src_i + 0];
z += cog_resample_table_4tap[y][2] * src[src_i + 1];
z += cog_resample_table_4tap[y][3] * src[src_i + 2];
z >>= 6;
dest[j] = CLAMP (z, 0, 255);
acc += scale;
}
for (; j < frame->components[component].width; j++) {
int src_i;
int y;
int z;
src_i = acc >> 8;
y = acc & 255;
z = 32;
z += cog_resample_table_4tap[y][0] * src[CLAMP (src_i - 1, 0, n_src - 1)];
z += cog_resample_table_4tap[y][1] * src[CLAMP (src_i + 0, 0, n_src - 1)];
z += cog_resample_table_4tap[y][2] * src[CLAMP (src_i + 1, 0, n_src - 1)];
z += cog_resample_table_4tap[y][3] * src[CLAMP (src_i + 2, 0, n_src - 1)];
z >>= 6;
dest[j] = CLAMP (z, 0, 255);
acc += scale;
} }
} }
@ -598,15 +701,21 @@ cog_virt_frame_new_horiz_resample (CogFrame * vf, int width)
{ {
CogFrame *virt_frame; CogFrame *virt_frame;
double *scale; double *scale;
int taps = 4;
virt_frame = cog_frame_new_virtual (NULL, vf->format, width, vf->height); virt_frame = cog_frame_new_virtual (NULL, vf->format, width, vf->height);
virt_frame->virt_frame1 = vf; virt_frame->virt_frame1 = vf;
virt_frame->render_line = cog_virt_frame_render_resample_horiz; if (taps == 1) {
virt_frame->render_line = cog_virt_frame_render_resample_horiz_1tap;
} else {
virt_frame->render_line = cog_virt_frame_render_resample_horiz_4tap;
}
scale = malloc (sizeof (double)); scale = malloc (sizeof (double));
virt_frame->virt_priv = scale; virt_frame->virt_priv = scale;
*scale = (double) vf->width / width; *scale = (double) vf->width / width;
virt_frame->param1 = 256.0 * (*scale);
return virt_frame; return virt_frame;
} }