mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
video-chroma: add chroma resampler
Add functions to up/downsample chroma in horizontal and vertical directions. These functions work in-placeand are meant to be used on the input/output of the pack/unpack functions.
This commit is contained in:
parent
2924365020
commit
0c60f0daa4
3 changed files with 786 additions and 0 deletions
|
@ -76,3 +76,743 @@ gst_video_chroma_to_string (GstVideoChromaSite site)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct _GstVideoChromaResample
|
||||
{
|
||||
GstVideoChromaMethod method;
|
||||
GstVideoChromaSite site;
|
||||
GstVideoChromaFlags flags;
|
||||
GstVideoFormat format;
|
||||
gint h_factor, v_factor;
|
||||
guint n_lines;
|
||||
gint offset;
|
||||
void (*h_resample) (GstVideoChromaResample * resample, gpointer pixels,
|
||||
gint width);
|
||||
void (*v_resample) (GstVideoChromaResample * resample, gpointer lines[],
|
||||
gint width);
|
||||
};
|
||||
|
||||
|
||||
#define PR(i) (p[2 + 4 * (i)])
|
||||
#define PB(i) (p[3 + 4 * (i)])
|
||||
|
||||
#define PR0(i) (l0[2 + 4 * (i)])
|
||||
#define PR1(i) (l1[2 + 4 * (i)])
|
||||
#define PR2(i) (l2[2 + 4 * (i)])
|
||||
#define PR3(i) (l3[2 + 4 * (i)])
|
||||
#define PB0(i) (l0[3 + 4 * (i)])
|
||||
#define PB1(i) (l1[3 + 4 * (i)])
|
||||
#define PB2(i) (l2[3 + 4 * (i)])
|
||||
#define PB3(i) (l3[3 + 4 * (i)])
|
||||
|
||||
#define FILT_1_1(a,b) ((a) + (b) + 1) >> 1
|
||||
#define FILT_1_1_1_1(a,b,c,d) ((a) + (b) + (c) + (d) + 2) >> 2
|
||||
|
||||
#define FILT_3_1(a,b) (3*(a) + (b) + 2) >> 2
|
||||
#define FILT_1_3(a,b) ((a) + 3*(b) + 2) >> 2
|
||||
#define FILT_1_2_1(a,b,c) ((a) + 2*(b) + (c) + 2) >> 2
|
||||
|
||||
#define FILT_7_1(a,b) (7*(a) + 1*(b) + 4) >> 3
|
||||
#define FILT_1_7(a,b) (1*(a) + 7*(b) + 4) >> 3
|
||||
|
||||
#define FILT_5_3(a,b) (5*(a) + 3*(b) + 4) >> 3
|
||||
#define FILT_3_5(a,b) (3*(a) + 5*(b) + 4) >> 3
|
||||
|
||||
#define FILT_10_3_2_1(a,b,c,d) (10*(a) + 3*(b) + 2*(c) + (d) + 8) >> 16
|
||||
#define FILT_1_2_3_10(a,b,c,d) ((a) + 2*(b) + 3*(c) + 10*(d) + 8) >> 16
|
||||
#define FILT_1_2_3_4_3_2_1(a,b,c,d,e,f,g) ((a) + 2*(b) + 3*(c) + 4*(d) + 3*(e) + 2*(f) + (g) + 8) >> 16
|
||||
|
||||
/* 2x horizontal upsampling without cositing
|
||||
*
|
||||
* +---------- a
|
||||
* | +------ (3*a + b + 2) >> 2
|
||||
* | | +---- ( a + 3*b + 2) >> 2
|
||||
* v v v
|
||||
* O-O-O-O-
|
||||
* x x
|
||||
* a b
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_H2(type) \
|
||||
static void \
|
||||
video_chroma_up_h2_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
type tr0, tr1; \
|
||||
type tb0, tb1; \
|
||||
\
|
||||
tr1 = PR(0); \
|
||||
tb1 = PB(0); \
|
||||
for (i = 1; i < width - 1; i += 2) { \
|
||||
tr0 = tr1, tr1 = PR(i+1); \
|
||||
tb0 = tb1, tb1 = PB(i+1); \
|
||||
\
|
||||
PR(i) = FILT_3_1 (tr0, tr1); \
|
||||
PB(i) = FILT_3_1 (tb0, tb1); \
|
||||
PR(i+1) = FILT_1_3 (tr0, tr1); \
|
||||
PB(i+1) = FILT_1_3 (tb0, tb1); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 2x vertical upsampling without cositing
|
||||
*
|
||||
* O--O--O- <---- a
|
||||
* a x x x
|
||||
* O--O--O- <---- (3*a + b + 2) >> 2
|
||||
* O--O--O- <-----( a + 3*b + 2) >> 2
|
||||
* b x x x
|
||||
* O--O--O- <---- b
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_V2(type) \
|
||||
static void \
|
||||
video_chroma_up_v2_##type (GstVideoChromaResample *resample, \
|
||||
gpointer lines[], gint width) \
|
||||
{ \
|
||||
gint i; \
|
||||
type *l0 = lines[0]; \
|
||||
type *l1 = lines[1]; \
|
||||
type tr0, tr1; \
|
||||
type tb0, tb1; \
|
||||
\
|
||||
if (resample->h_resample) { \
|
||||
resample->h_resample (resample, l0, width); \
|
||||
if (l0 != l1) \
|
||||
resample->h_resample (resample, l1, width); \
|
||||
} \
|
||||
if (l0 != l1) { \
|
||||
for (i = 0; i < width; i++) { \
|
||||
tr0 = PR0(i), tr1 = PR1(i); \
|
||||
tb0 = PB0(i), tb1 = PB1(i); \
|
||||
\
|
||||
PR0(i) = FILT_3_1 (tr0, tr1); \
|
||||
PB0(i) = FILT_3_1 (tb0, tb1); \
|
||||
PR1(i) = FILT_1_3 (tr0, tr1); \
|
||||
PB1(i) = FILT_1_3 (tb0, tb1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/* 2x vertical upsampling interlaced without cositing
|
||||
*
|
||||
* even odd
|
||||
*
|
||||
* O--O--O--------------- <--- a
|
||||
* a x x x
|
||||
* --------------O--O--O- <--- c
|
||||
* O--O--O--------------- <--- (5*a + 3*b + 4) >> 3
|
||||
* c x x x
|
||||
* --------------O--O--O- <--- (7*c + d + 4) >> 3
|
||||
* O--O--O--------------- <--- ( a + 7*b + 4) >> 3
|
||||
* b x x x
|
||||
* --------------O--O--O- <--- (3*c + 5*d + 4) >> 3
|
||||
* O--O--O---------------
|
||||
* d x x x
|
||||
* --------------O--O--O-
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_VI2(type) \
|
||||
static void \
|
||||
video_chroma_up_vi2_##type (GstVideoChromaResample *resample, \
|
||||
gpointer lines[], gint width) \
|
||||
{ \
|
||||
gint i; \
|
||||
type *l0 = lines[0]; \
|
||||
type *l1 = lines[1]; \
|
||||
type *l2 = lines[2]; \
|
||||
type *l3 = lines[3]; \
|
||||
type tr0, tr1, tr2, tr3; \
|
||||
type tb0, tb1, tb2, tb3; \
|
||||
\
|
||||
if (resample->h_resample) { \
|
||||
if (l0 != l1) { \
|
||||
resample->h_resample (resample, l0, width); \
|
||||
resample->h_resample (resample, l1, width); \
|
||||
} \
|
||||
if (l2 != l3) { \
|
||||
resample->h_resample (resample, l2, width); \
|
||||
resample->h_resample (resample, l3, width); \
|
||||
} \
|
||||
} \
|
||||
if (l0 != l1 && l2 != l3) { \
|
||||
for (i = 0; i < width; i++) { \
|
||||
tr0 = PR0(i), tr2 = PR2(i); \
|
||||
tb0 = PB0(i), tb2 = PB2(i); \
|
||||
tr1 = PR1(i), tr3 = PR3(i); \
|
||||
tb1 = PB1(i), tb3 = PB3(i); \
|
||||
\
|
||||
PR0(i) = FILT_5_3 (tr0, tr2); \
|
||||
PB0(i) = FILT_5_3 (tb0, tb2); \
|
||||
PR1(i) = FILT_7_1 (tr1, tr3); \
|
||||
PB1(i) = FILT_7_1 (tb1, tb3); \
|
||||
PR2(i) = FILT_1_7 (tr0, tr2); \
|
||||
PB2(i) = FILT_1_7 (tb0, tb2); \
|
||||
PR3(i) = FILT_3_5 (tr1, tr3); \
|
||||
PB3(i) = FILT_3_5 (tb1, tb3); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 2x horizontal downsampling without cositing
|
||||
*
|
||||
* +------ (a + b+ 1) >> 1
|
||||
* |
|
||||
* v
|
||||
* -O---O--
|
||||
* x x x x
|
||||
* a b c d
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_H2(type) \
|
||||
static void \
|
||||
video_chroma_down_h2_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
for (i = 0; i < width - 1; i += 2) { \
|
||||
type tr0 = PR(i), tr1 = PR(i+1); \
|
||||
type tb0 = PB(i), tb1 = PB(i+1); \
|
||||
\
|
||||
PR(i) = FILT_1_1 (tr0, tr1); \
|
||||
PB(i) = FILT_1_1 (tb0, tb1); \
|
||||
} \
|
||||
}
|
||||
/* 2x vertical downsampling without cositing
|
||||
*
|
||||
* a x--x--x-
|
||||
* O O O <---- (a + b + 1) >> 1
|
||||
* b x--x--x-
|
||||
* c x--x--x-
|
||||
* O O O
|
||||
* d x--x--x-
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_V2(type) \
|
||||
static void \
|
||||
video_chroma_down_v2_##type (GstVideoChromaResample *resample, \
|
||||
gpointer lines[], gint width) \
|
||||
{ \
|
||||
gint i; \
|
||||
type *l0 = lines[0]; \
|
||||
type *l1 = lines[1]; \
|
||||
\
|
||||
if (resample->h_resample) { \
|
||||
resample->h_resample (resample, l0, width); \
|
||||
if (l0 != l1) \
|
||||
resample->h_resample (resample, l1, width); \
|
||||
} \
|
||||
if (l0 != l1) { \
|
||||
for (i = 0; i < width; i++) { \
|
||||
type tr0 = PR0(i), tr1 = PR1(i); \
|
||||
type tb0 = PB0(i), tb1 = PB1(i); \
|
||||
\
|
||||
PR0(i) = FILT_1_1 (tr0, tr1); \
|
||||
PB0(i) = FILT_1_1 (tb0, tb1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_UPSAMPLE_H2 (guint16);
|
||||
MAKE_UPSAMPLE_H2 (guint8);
|
||||
MAKE_UPSAMPLE_V2 (guint16);
|
||||
MAKE_UPSAMPLE_V2 (guint8);
|
||||
MAKE_UPSAMPLE_VI2 (guint16);
|
||||
MAKE_UPSAMPLE_VI2 (guint8);
|
||||
MAKE_DOWNSAMPLE_H2 (guint16);
|
||||
MAKE_DOWNSAMPLE_H2 (guint8);
|
||||
MAKE_DOWNSAMPLE_V2 (guint16);
|
||||
MAKE_DOWNSAMPLE_V2 (guint8);
|
||||
|
||||
/* 4x horizontal upsampling without cositing
|
||||
*
|
||||
* +---------- (7*a + b + 4) >> 3
|
||||
* | +-------- (5*a + 3*b + 4) >> 3
|
||||
* a a | | +------ (3*a + 5*b + 4) >> 3
|
||||
* | | | | | +---- ( a + 7*b + 4) >> 3
|
||||
* v v v v v v
|
||||
* O-O-O-O-O-O-O-O-
|
||||
* x x
|
||||
* a b
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_H4(type) \
|
||||
static void \
|
||||
video_chroma_up_h4_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
type tr0, tr1; \
|
||||
type tb0, tb1; \
|
||||
\
|
||||
tr1 = PR(0); \
|
||||
tb1 = PB(0); \
|
||||
for (i = 2; i < width - 3; i += 4) { \
|
||||
tr0 = tr1, tr1 = PR(i+2); \
|
||||
tb0 = tb1, tb1 = PB(i+2); \
|
||||
\
|
||||
PR(i) = FILT_7_1 (tr0, tr1); \
|
||||
PB(i) = FILT_7_1 (tb0, tb1); \
|
||||
PR(i+1) = FILT_5_3 (tr0, tr1); \
|
||||
PB(i+1) = FILT_5_3 (tb0, tb1); \
|
||||
PR(i+2) = FILT_3_5 (tr0, tr1); \
|
||||
PB(i+2) = FILT_3_5 (tb0, tb1); \
|
||||
PR(i+3) = FILT_1_7 (tr0, tr1); \
|
||||
PB(i+3) = FILT_1_7 (tb0, tb1); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 4x vertical upsampling without cositing
|
||||
*
|
||||
* O--O--O- <---- a
|
||||
* O--O--O- <---- a
|
||||
* a x x x
|
||||
* O--O--O- <---- (7*a + b + 4) >> 3
|
||||
* O--O--O- <---- (5*a + 3*b + 4) >> 3
|
||||
* O--O--O- <---- (3*a + 5*b + 4) >> 3
|
||||
* O--O--O- <-----( a + 7*b + 4) >> 3
|
||||
* b x x x
|
||||
* O--O--O-
|
||||
* O--O--O-
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_V4(type) \
|
||||
static void \
|
||||
video_chroma_up_v4_##type (GstVideoChromaResample *resample, \
|
||||
gpointer lines[], gint width) \
|
||||
{ \
|
||||
gint i; \
|
||||
type *l0 = lines[0]; \
|
||||
type *l1 = lines[1]; \
|
||||
type *l2 = lines[2]; \
|
||||
type *l3 = lines[3]; \
|
||||
type tr0, tr1; \
|
||||
type tb0, tb1; \
|
||||
\
|
||||
if (resample->h_resample) { \
|
||||
if (l0 != l1) { \
|
||||
resample->h_resample (resample, l0, width); \
|
||||
resample->h_resample (resample, l1, width); \
|
||||
} \
|
||||
if (l2 != l3) { \
|
||||
resample->h_resample (resample, l2, width); \
|
||||
resample->h_resample (resample, l3, width); \
|
||||
} \
|
||||
} \
|
||||
if (l0 != l1 && l2 != l3) { \
|
||||
for (i = 0; i < width; i++) { \
|
||||
tr0 = PR0(i), tr1 = PR2(i); \
|
||||
tb0 = PB0(i), tb1 = PB2(i); \
|
||||
\
|
||||
PR0(i) = FILT_7_1 (tr0, tr1); \
|
||||
PB0(i) = FILT_7_1 (tb0, tb1); \
|
||||
PR1(i) = FILT_5_3 (tr0, tr1); \
|
||||
PB1(i) = FILT_5_3 (tb0, tb1); \
|
||||
PR2(i) = FILT_3_5 (tr0, tr1); \
|
||||
PB2(i) = FILT_3_5 (tb0, tb1); \
|
||||
PR3(i) = FILT_1_7 (tr0, tr1); \
|
||||
PB3(i) = FILT_1_7 (tb0, tb1); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 4x horizontal downsampling without cositing
|
||||
*
|
||||
* +------ (a + b + c + d + 2) >> 2
|
||||
* |
|
||||
* v
|
||||
* ---O-------O---
|
||||
* x x x x x x x x
|
||||
* a b c d e f g h
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_H4(type) \
|
||||
static void \
|
||||
video_chroma_down_h4_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
for (i = 0; i < width - 4; i += 4) { \
|
||||
type tr0 = PR(i), tr1 = PR(i+1), tr2 = PR(i+2), tr3 = PR(i+3); \
|
||||
type tb0 = PB(i), tb1 = PB(i+1), tb2 = PB(i+2), tb3 = PB(i+3); \
|
||||
\
|
||||
PR(i) = FILT_1_1_1_1 (tr0, tr1, tr2, tr3); \
|
||||
PB(i) = FILT_1_1_1_1 (tb0, tb1, tb2, tb3); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 4x vertical downsampling without cositing
|
||||
*
|
||||
* a x--x--x-
|
||||
* b x--x--x-
|
||||
* O O O <---- (a + b + c + d + 2) >> 2
|
||||
* c x--x--x-
|
||||
* d x--x--x-
|
||||
* e x--x--x-
|
||||
* f x--x--x-
|
||||
* O O O
|
||||
* g x--x--x-
|
||||
* h x--x--x-
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_V4(type) \
|
||||
static void \
|
||||
video_chroma_down_v4_##type (GstVideoChromaResample *resample, \
|
||||
gpointer lines[], gint width) \
|
||||
{ \
|
||||
gint i; \
|
||||
type *l0 = lines[0]; \
|
||||
type *l1 = lines[1]; \
|
||||
type *l2 = lines[2]; \
|
||||
type *l3 = lines[3]; \
|
||||
\
|
||||
if (resample->h_resample) { \
|
||||
resample->h_resample (resample, l0, width); \
|
||||
if (l0 != l1) \
|
||||
resample->h_resample (resample, l1, width); \
|
||||
if (l1 != l2) \
|
||||
resample->h_resample (resample, l2, width); \
|
||||
if (l2 != l3) \
|
||||
resample->h_resample (resample, l3, width); \
|
||||
} \
|
||||
for (i = 0; i < width; i++) { \
|
||||
type tr0 = PR0(i), tr1 = PR1(i); \
|
||||
type tr2 = PR2(i), tr3 = PR3(i); \
|
||||
type tb0 = PB0(i), tb1 = PB1(i); \
|
||||
type tb2 = PB2(i), tb3 = PB3(i); \
|
||||
\
|
||||
PR0(i) = FILT_1_1_1_1 (tr0, tr1, tr2, tr3); \
|
||||
PB0(i) = FILT_1_1_1_1 (tb0, tb1, tb2, tb3); \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_UPSAMPLE_H4 (guint16);
|
||||
MAKE_UPSAMPLE_H4 (guint8);
|
||||
MAKE_UPSAMPLE_V4 (guint16);
|
||||
MAKE_UPSAMPLE_V4 (guint8);
|
||||
MAKE_DOWNSAMPLE_H4 (guint16);
|
||||
MAKE_DOWNSAMPLE_H4 (guint8);
|
||||
MAKE_DOWNSAMPLE_V4 (guint16);
|
||||
MAKE_DOWNSAMPLE_V4 (guint8);
|
||||
|
||||
/* 2x upsampling with cositing
|
||||
*
|
||||
* a +------ (a + b + 1) >> 1
|
||||
* | |
|
||||
* v v
|
||||
* O-O-O-O
|
||||
* x x
|
||||
* a b
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_H2_CS(type) \
|
||||
static void \
|
||||
video_chroma_up_h2_cs_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
for (i = 1; i < width - 1; i += 2) { \
|
||||
PR(i) = FILT_1_1 (PR(i-1), PR(i+1)); \
|
||||
PB(i) = FILT_1_1 (PB(i-1), PB(i+1)); \
|
||||
} \
|
||||
}
|
||||
/* 2x downsampling with cositing
|
||||
*
|
||||
* a
|
||||
* | +------ (b + 2*c + d + 2) >> 2
|
||||
* v v
|
||||
* O---O---O---
|
||||
* x x x x x x
|
||||
* a b c d e f
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_H2_CS(type) \
|
||||
static void \
|
||||
video_chroma_down_h2_cs_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
if (width < 2) \
|
||||
return; \
|
||||
\
|
||||
PR(0) = FILT_3_1 (PR(0), PR(1)); \
|
||||
PB(0) = FILT_3_1 (PB(0), PB(1)); \
|
||||
\
|
||||
for (i = 2; i < width - 2; i += 2) { \
|
||||
PR(i) = FILT_1_2_1 (PR(i-1), PR(i), PR(i+1)); \
|
||||
PB(i) = FILT_1_2_1 (PB(i-1), PB(i), PB(i+1)); \
|
||||
} \
|
||||
if (i < width) { \
|
||||
PR(i) = FILT_1_3 (PR(i-1), PR(i)); \
|
||||
PB(i) = FILT_1_3 (PB(i-1), PB(i)); \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_UPSAMPLE_H2_CS (guint16);
|
||||
MAKE_UPSAMPLE_H2_CS (guint8);
|
||||
MAKE_DOWNSAMPLE_H2_CS (guint16);
|
||||
MAKE_DOWNSAMPLE_H2_CS (guint8);
|
||||
|
||||
/* 4x upsampling with cositing
|
||||
*
|
||||
* +---------- (3*a + b + 2) >> 2
|
||||
* a | +-------- ( a + b + 1) >> 1
|
||||
* | | | +------ ( a + 3*b + 2) >> 2
|
||||
* v v v v
|
||||
* O-O-O-O-O-O-O-O
|
||||
* x x
|
||||
* a b
|
||||
*/
|
||||
#define MAKE_UPSAMPLE_H4_CS(type) \
|
||||
static void \
|
||||
video_chroma_up_h4_cs_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
for (i = 0; i < width - 4; i += 4) { \
|
||||
type tr0 = PR(i), tr1 = PR(i+4); \
|
||||
type tb0 = PB(i), tb1 = PB(i+4); \
|
||||
\
|
||||
PR(i+1) = FILT_3_1 (tr0, tr1); \
|
||||
PB(i+1) = FILT_3_1 (tb0, tb1); \
|
||||
PR(i+2) = FILT_1_1 (tr0, tr1); \
|
||||
PB(i+2) = FILT_1_1 (tb0, tb1); \
|
||||
PR(i+3) = FILT_1_3 (tr0, tr1); \
|
||||
PB(i+3) = FILT_1_3 (tb0, tb1); \
|
||||
} \
|
||||
}
|
||||
/* 4x downsampling with cositing
|
||||
*
|
||||
* a
|
||||
* | +------ (b + 2*c + 3*d + 4*e + 3*f + 2*g + h + 8) >> 16
|
||||
* v v
|
||||
* O-------O-------
|
||||
* x x x x x x x x
|
||||
* a b c d e f g h
|
||||
*/
|
||||
#define MAKE_DOWNSAMPLE_H4_CS(type) \
|
||||
static void \
|
||||
video_chroma_down_h4_cs_##type (GstVideoChromaResample *resample, \
|
||||
gpointer pixels, gint width) \
|
||||
{ \
|
||||
type *p = pixels; \
|
||||
gint i; \
|
||||
\
|
||||
if (width < 4) \
|
||||
return; \
|
||||
\
|
||||
PR(0) = FILT_10_3_2_1 (PR(0), PR(1), PR(2), PR(3)); \
|
||||
PB(0) = FILT_10_3_2_1 (PB(0), PB(1), PB(2), PB(3)); \
|
||||
\
|
||||
for (i = 4; i < width - 4; i += 4) { \
|
||||
PR(i) = FILT_1_2_3_4_3_2_1 (PR(i-3), PR(i-2), PR(i-1), PR(i), PR(i+1), PR(i+2), PR(i+3)); \
|
||||
PB(i) = FILT_1_2_3_4_3_2_1 (PB(i-3), PB(i-2), PB(i-1), PB(i), PB(i+1), PB(i+2), PB(i+3)); \
|
||||
} \
|
||||
if (i < width) { \
|
||||
PR(i) = FILT_1_2_3_10 (PR(i-3), PR(i-2), PR(i-1), PR(i)); \
|
||||
PB(i) = FILT_1_2_3_10 (PB(i-3), PB(i-2), PB(i-1), PB(i)); \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_UPSAMPLE_H4_CS (guint16);
|
||||
MAKE_UPSAMPLE_H4_CS (guint8);
|
||||
MAKE_DOWNSAMPLE_H4_CS (guint16);
|
||||
MAKE_DOWNSAMPLE_H4_CS (guint8);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*resample) (GstVideoChromaResample * resample, gpointer pixels,
|
||||
gint width);
|
||||
} HorizResampler;
|
||||
|
||||
static const HorizResampler h_resamplers[] = {
|
||||
{NULL},
|
||||
{video_chroma_up_h2_guint8},
|
||||
{video_chroma_down_h2_guint8},
|
||||
{video_chroma_up_h2_guint16},
|
||||
{video_chroma_down_h2_guint16},
|
||||
{video_chroma_up_h2_cs_guint8},
|
||||
{video_chroma_down_h2_cs_guint8},
|
||||
{video_chroma_up_h2_cs_guint16},
|
||||
{video_chroma_down_h2_cs_guint16},
|
||||
{video_chroma_up_h4_guint8},
|
||||
{video_chroma_down_h4_guint8},
|
||||
{video_chroma_up_h4_guint16},
|
||||
{video_chroma_down_h4_guint16},
|
||||
{video_chroma_up_h4_cs_guint8},
|
||||
{video_chroma_down_h4_cs_guint8},
|
||||
{video_chroma_up_h4_cs_guint16},
|
||||
{video_chroma_down_h4_cs_guint16}
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*resample) (GstVideoChromaResample * resample, gpointer lines[],
|
||||
gint width);
|
||||
guint n_lines;
|
||||
gint offset;
|
||||
} VertResampler;
|
||||
|
||||
static void
|
||||
video_chroma_none (GstVideoChromaResample * resample,
|
||||
gpointer lines[], gint width)
|
||||
{
|
||||
if (resample->h_resample)
|
||||
resample->h_resample (resample, lines[0], width);
|
||||
}
|
||||
|
||||
static const VertResampler v_resamplers[] = {
|
||||
{video_chroma_none, 1, 0},
|
||||
{video_chroma_up_v2_guint8, 2, -1},
|
||||
{video_chroma_down_v2_guint8, 2, 0},
|
||||
{video_chroma_up_v2_guint16, 2, -1},
|
||||
{video_chroma_down_v2_guint16, 2, 0},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{video_chroma_up_v4_guint8, 4, -2},
|
||||
{video_chroma_down_v4_guint8, 4, 0},
|
||||
{video_chroma_up_v4_guint16, 4, -2},
|
||||
{video_chroma_down_v4_guint16, 4, 0},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{video_chroma_up_vi2_guint8, 4, -2},
|
||||
{NULL},
|
||||
{video_chroma_up_vi2_guint16, 4, -2},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* gst_video_chroma_resample_new:
|
||||
* @method: a #GstVideoChromaMethod
|
||||
* @site: a #GstVideoChromaSite
|
||||
* @flags: #GstVideoChromaFlags
|
||||
* @format: the #GstVideoFormat
|
||||
* @h_factor: horizontal resampling factor
|
||||
* @v_factor: vertical resampling factor
|
||||
*
|
||||
* Create a new resampler object for the given parameters. When @h_factor or
|
||||
* @v_factoris > 0, upsampling will be used, otherwise subsampling is
|
||||
* performed.
|
||||
*
|
||||
* Returns: a new #GstVideoChromaResample that should be freed with
|
||||
* gst_video_chroma_resample_free() after usage.
|
||||
*/
|
||||
GstVideoChromaResample *
|
||||
gst_video_chroma_resample_new (GstVideoChromaMethod method,
|
||||
GstVideoChromaSite site, GstVideoChromaFlags flags,
|
||||
GstVideoFormat format, gint h_factor, gint v_factor)
|
||||
{
|
||||
GstVideoChromaResample *result;
|
||||
guint cosite, h_index, v_index, bits;
|
||||
|
||||
/* no resampling */
|
||||
if (h_factor == 0 && v_factor == 0)
|
||||
return NULL;
|
||||
|
||||
if (format == GST_VIDEO_FORMAT_AYUV)
|
||||
bits = 8;
|
||||
else if (format == GST_VIDEO_FORMAT_AYUV64)
|
||||
bits = 16;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
cosite = (site & GST_VIDEO_CHROMA_SITE_H_COSITED ? 1 : 0);
|
||||
if (h_factor == 0)
|
||||
h_index = 0;
|
||||
else
|
||||
h_index =
|
||||
((ABS (h_factor) - 1) * 8) + (cosite ? 4 : 0) + (bits ==
|
||||
16 ? 2 : 0) + (h_factor < 0 ? 1 : 0) + 1;
|
||||
cosite = (site & GST_VIDEO_CHROMA_SITE_V_COSITED ? 1 : 0);
|
||||
if (v_factor == 0)
|
||||
v_index = 0;
|
||||
else
|
||||
v_index =
|
||||
((ABS (v_factor) - 1) * 8) + (cosite ? 4 : 0) + (bits ==
|
||||
16 ? 2 : 0) + (v_factor < 0 ? 1 : 0) + 1;
|
||||
|
||||
result = g_slice_new (GstVideoChromaResample);
|
||||
result->method = method;
|
||||
result->site = site;
|
||||
result->flags = flags;
|
||||
result->format = format;
|
||||
result->h_factor = h_factor;
|
||||
result->v_factor = v_factor;
|
||||
result->h_resample = h_resamplers[h_index].resample;
|
||||
result->v_resample = v_resamplers[v_index].resample;
|
||||
result->n_lines = v_resamplers[v_index].n_lines;
|
||||
result->offset = v_resamplers[v_index].offset;
|
||||
|
||||
GST_DEBUG ("select resample %p %d, factor %d, "
|
||||
"cosite %d, bits %d", result, h_index, h_factor, cosite, bits);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_chroma_resample_get_info:
|
||||
* @resample: a #GstVideoChromaResample
|
||||
* @n_lines: the number of input lines
|
||||
* @offset: the first line
|
||||
*
|
||||
* The resampler must be fed @n_lines at a time. The first line should be
|
||||
* at @offset.
|
||||
*/
|
||||
void
|
||||
gst_video_chroma_resample_get_info (GstVideoChromaResample * resample,
|
||||
guint * n_lines, gint * offset)
|
||||
{
|
||||
g_return_if_fail (resample != NULL);
|
||||
|
||||
if (n_lines)
|
||||
*n_lines = resample->n_lines;
|
||||
if (offset)
|
||||
*offset = resample->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_chroma_resample_free:
|
||||
* @resample: a #GstVideoChromaResample
|
||||
*
|
||||
* Free @resample
|
||||
*/
|
||||
void
|
||||
gst_video_chroma_resample_free (GstVideoChromaResample * resample)
|
||||
{
|
||||
g_return_if_fail (resample != NULL);
|
||||
|
||||
g_slice_free (GstVideoChromaResample, resample);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_chroma_resample:
|
||||
* @resample: a #GstVideoChromaResample
|
||||
* @lines: pixel lines
|
||||
* @width: the number of pixels on one line
|
||||
*
|
||||
* Perform resampling of @width chroma pixels in @lines.
|
||||
*/
|
||||
void
|
||||
gst_video_chroma_resample (GstVideoChromaResample * resample,
|
||||
gpointer lines[], gint width)
|
||||
{
|
||||
g_return_if_fail (resample != NULL);
|
||||
|
||||
resample->v_resample (resample, lines, width);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,46 @@ typedef enum {
|
|||
GstVideoChromaSite gst_video_chroma_from_string (const gchar * s);
|
||||
const gchar * gst_video_chroma_to_string (GstVideoChromaSite site);
|
||||
|
||||
/**
|
||||
* GstVideoChromaMethod:
|
||||
* @GST_VIDEO_CHROMA_METHOD_NEAREST: Duplicates the chroma samples when
|
||||
* upsampling and drops when subsampling
|
||||
* @GST_VIDEO_CHROMA_METHOD_LINEAR: Uses linear interpolation to reconstruct
|
||||
* missing chroma and averaging to subsample
|
||||
*
|
||||
* Different subsampling and upsampling methods
|
||||
*/
|
||||
typedef enum {
|
||||
GST_VIDEO_CHROMA_METHOD_NEAREST,
|
||||
GST_VIDEO_CHROMA_METHOD_LINEAR
|
||||
} GstVideoChromaMethod;
|
||||
|
||||
/**
|
||||
* GstVideoChromaFlags:
|
||||
* @GST_VIDEO_CHROMA_FLAG_NONE: no flags
|
||||
*
|
||||
* Extra flags that influence the result from gst_video_chroma_resample_new()
|
||||
* and extra features of the returned resampler.
|
||||
*/
|
||||
typedef enum {
|
||||
GST_VIDEO_CHROMA_FLAG_NONE = 0,
|
||||
} GstVideoChromaFlags;
|
||||
|
||||
typedef struct _GstVideoChromaResample GstVideoChromaResample;
|
||||
|
||||
GstVideoChromaResample * gst_video_chroma_resample_new (GstVideoChromaMethod method,
|
||||
GstVideoChromaSite site,
|
||||
GstVideoChromaFlags flags,
|
||||
GstVideoFormat format,
|
||||
gint h_factor, gint v_factor);
|
||||
void gst_video_chroma_resample_free (GstVideoChromaResample *resample);
|
||||
|
||||
void gst_video_chroma_resample_get_info (GstVideoChromaResample *resample,
|
||||
guint * n_lines, gint *offset);
|
||||
|
||||
void gst_video_chroma_resample (GstVideoChromaResample *resample,
|
||||
gpointer lines[], gint width);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_VIDEO_CHROMA_H__ */
|
||||
|
|
|
@ -51,7 +51,13 @@ EXPORTS
|
|||
gst_video_buffer_pool_get_type
|
||||
gst_video_buffer_pool_new
|
||||
gst_video_calculate_display_ratio
|
||||
gst_video_chroma_flags_get_type
|
||||
gst_video_chroma_from_string
|
||||
gst_video_chroma_method_get_type
|
||||
gst_video_chroma_resample
|
||||
gst_video_chroma_resample_free
|
||||
gst_video_chroma_resample_get_info
|
||||
gst_video_chroma_resample_new
|
||||
gst_video_chroma_site_get_type
|
||||
gst_video_chroma_to_string
|
||||
gst_video_codec_frame_get_type
|
||||
|
|
Loading…
Reference in a new issue