mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 01:45:33 +00:00
videoscale: Add modified Lanczos scaling method
Adds a Lanczos-derived scaling method, which is rather slow, but very high quality. Adds a few properties that can be used to tune various scaling properties: sharpness, sharpen, envelope, dither. Not currently Orcified, but was designed with that in mind.
This commit is contained in:
parent
924f743981
commit
4e38577b30
5 changed files with 1689 additions and 4 deletions
|
@ -8,7 +8,8 @@ libgstvideoscale_la_SOURCES = \
|
||||||
vs_image.c \
|
vs_image.c \
|
||||||
vs_scanline.c \
|
vs_scanline.c \
|
||||||
vs_4tap.c \
|
vs_4tap.c \
|
||||||
vs_fill_borders.c
|
vs_fill_borders.c \
|
||||||
|
vs_lanczos.c
|
||||||
|
|
||||||
nodist_libgstvideoscale_la_SOURCES = $(ORC_NODIST_SOURCES)
|
nodist_libgstvideoscale_la_SOURCES = $(ORC_NODIST_SOURCES)
|
||||||
|
|
||||||
|
|
|
@ -89,13 +89,22 @@ GST_DEBUG_CATEGORY (video_scale_debug);
|
||||||
|
|
||||||
#define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR
|
#define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR
|
||||||
#define DEFAULT_PROP_ADD_BORDERS FALSE
|
#define DEFAULT_PROP_ADD_BORDERS FALSE
|
||||||
|
#define DEFAULT_PROP_SHARPNESS 1.0
|
||||||
|
#define DEFAULT_PROP_SHARPEN 0.0
|
||||||
|
#define DEFAULT_PROP_DITHER FALSE
|
||||||
|
#define DEFAULT_PROP_SUBMETHOD 1
|
||||||
|
#define DEFAULT_PROP_ENVELOPE 2.0
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_METHOD,
|
PROP_METHOD,
|
||||||
PROP_ADD_BORDERS
|
PROP_ADD_BORDERS,
|
||||||
/* FILL ME */
|
PROP_SHARPNESS,
|
||||||
|
PROP_SHARPEN,
|
||||||
|
PROP_DITHER,
|
||||||
|
PROP_SUBMETHOD,
|
||||||
|
PROP_ENVELOPE
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef GST_VIDEO_SIZE_RANGE
|
#undef GST_VIDEO_SIZE_RANGE
|
||||||
|
@ -144,6 +153,7 @@ gst_video_scale_method_get_type (void)
|
||||||
{GST_VIDEO_SCALE_NEAREST, "Nearest Neighbour", "nearest-neighbour"},
|
{GST_VIDEO_SCALE_NEAREST, "Nearest Neighbour", "nearest-neighbour"},
|
||||||
{GST_VIDEO_SCALE_BILINEAR, "Bilinear", "bilinear"},
|
{GST_VIDEO_SCALE_BILINEAR, "Bilinear", "bilinear"},
|
||||||
{GST_VIDEO_SCALE_4TAP, "4-tap", "4-tap"},
|
{GST_VIDEO_SCALE_4TAP, "4-tap", "4-tap"},
|
||||||
|
{GST_VIDEO_SCALE_LANCZOS, "Lanczos", "lanczos"},
|
||||||
{0, NULL, NULL},
|
{0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,6 +261,36 @@ gst_video_scale_class_init (GstVideoScaleClass * klass)
|
||||||
DEFAULT_PROP_ADD_BORDERS,
|
DEFAULT_PROP_ADD_BORDERS,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SHARPNESS,
|
||||||
|
g_param_spec_double ("sharpness", "Sharpness",
|
||||||
|
"Sharpness of filter", 0.0, 2.0, DEFAULT_PROP_SHARPNESS,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SHARPEN,
|
||||||
|
g_param_spec_double ("sharpen", "Sharpen",
|
||||||
|
"Sharpening", 0.0, 1.0, DEFAULT_PROP_SHARPEN,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_DITHER,
|
||||||
|
g_param_spec_boolean ("dither", "Dither",
|
||||||
|
"Add dither (only used for Lanczos method)",
|
||||||
|
DEFAULT_PROP_DITHER,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* I am hiding submethod for now, since it's poorly named, poorly
|
||||||
|
* documented, and will probably just get people into trouble. */
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SUBMETHOD,
|
||||||
|
g_param_spec_int ("submethod", "submethod",
|
||||||
|
"submethod", 0, 3, DEFAULT_PROP_SUBMETHOD,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ENVELOPE,
|
||||||
|
g_param_spec_double ("envelope", "Envelope",
|
||||||
|
"Size of filter envelope", 0.0, 5.0, DEFAULT_PROP_ENVELOPE,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
trans_class->transform_caps =
|
trans_class->transform_caps =
|
||||||
GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps);
|
GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps);
|
||||||
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_scale_set_caps);
|
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_scale_set_caps);
|
||||||
|
@ -267,6 +307,11 @@ gst_video_scale_init (GstVideoScale * videoscale, GstVideoScaleClass * klass)
|
||||||
videoscale->tmp_buf = NULL;
|
videoscale->tmp_buf = NULL;
|
||||||
videoscale->method = DEFAULT_PROP_METHOD;
|
videoscale->method = DEFAULT_PROP_METHOD;
|
||||||
videoscale->add_borders = DEFAULT_PROP_ADD_BORDERS;
|
videoscale->add_borders = DEFAULT_PROP_ADD_BORDERS;
|
||||||
|
videoscale->submethod = DEFAULT_PROP_SUBMETHOD;
|
||||||
|
videoscale->sharpness = DEFAULT_PROP_SHARPNESS;
|
||||||
|
videoscale->sharpen = DEFAULT_PROP_SHARPEN;
|
||||||
|
videoscale->dither = DEFAULT_PROP_DITHER;
|
||||||
|
videoscale->envelope = DEFAULT_PROP_ENVELOPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -296,6 +341,31 @@ gst_video_scale_set_property (GObject * object, guint prop_id,
|
||||||
GST_OBJECT_UNLOCK (vscale);
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (vscale));
|
gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (vscale));
|
||||||
break;
|
break;
|
||||||
|
case PROP_SHARPNESS:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
vscale->sharpness = g_value_get_double (value);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_SHARPEN:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
vscale->sharpen = g_value_get_double (value);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_DITHER:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
vscale->dither = g_value_get_boolean (value);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_SUBMETHOD:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
vscale->submethod = g_value_get_int (value);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_ENVELOPE:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
vscale->envelope = g_value_get_double (value);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -319,6 +389,31 @@ gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
g_value_set_boolean (value, vscale->add_borders);
|
g_value_set_boolean (value, vscale->add_borders);
|
||||||
GST_OBJECT_UNLOCK (vscale);
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SHARPNESS:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_double (value, vscale->sharpness);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_SHARPEN:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_double (value, vscale->sharpen);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_DITHER:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_boolean (value, vscale->dither);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_SUBMETHOD:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_int (value, vscale->submethod);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
|
case PROP_ENVELOPE:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_double (value, vscale->envelope);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -1078,6 +1173,11 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
|
||||||
case GST_VIDEO_SCALE_4TAP:
|
case GST_VIDEO_SCALE_4TAP:
|
||||||
vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf);
|
vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_SCALE_LANCZOS:
|
||||||
|
vs_image_scale_lanczos_AYUV (&dest, &src, videoscale->tmp_buf,
|
||||||
|
videoscale->sharpness, videoscale->dither, videoscale->submethod,
|
||||||
|
videoscale->envelope, videoscale->sharpen);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto unknown_mode;
|
goto unknown_mode;
|
||||||
}
|
}
|
||||||
|
@ -1217,6 +1317,17 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
|
||||||
vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
|
vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
|
||||||
vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_SCALE_LANCZOS:
|
||||||
|
vs_image_scale_lanczos_Y (&dest, &src, videoscale->tmp_buf,
|
||||||
|
videoscale->sharpness, videoscale->dither, videoscale->submethod,
|
||||||
|
videoscale->envelope, videoscale->sharpen);
|
||||||
|
vs_image_scale_lanczos_Y (&dest_u, &src_u, videoscale->tmp_buf,
|
||||||
|
videoscale->sharpness, videoscale->dither, videoscale->submethod,
|
||||||
|
videoscale->envelope, videoscale->sharpen);
|
||||||
|
vs_image_scale_lanczos_Y (&dest_v, &src_v, videoscale->tmp_buf,
|
||||||
|
videoscale->sharpness, videoscale->dither, videoscale->submethod,
|
||||||
|
videoscale->envelope, videoscale->sharpen);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto unknown_mode;
|
goto unknown_mode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,15 @@ GST_DEBUG_CATEGORY_EXTERN (video_scale_debug);
|
||||||
* @GST_VIDEO_SCALE_NEAREST: use nearest neighbour scaling (fast and ugly)
|
* @GST_VIDEO_SCALE_NEAREST: use nearest neighbour scaling (fast and ugly)
|
||||||
* @GST_VIDEO_SCALE_BILINEAR: use bilinear scaling (slower but prettier).
|
* @GST_VIDEO_SCALE_BILINEAR: use bilinear scaling (slower but prettier).
|
||||||
* @GST_VIDEO_SCALE_4TAP: use a 4-tap filter for scaling (slow).
|
* @GST_VIDEO_SCALE_4TAP: use a 4-tap filter for scaling (slow).
|
||||||
|
* @GST_VIDEO_SCALE_LANCZOS: use a multitap Lanczos filter for scaling (slow).
|
||||||
*
|
*
|
||||||
* The videoscale method to use.
|
* The videoscale method to use.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_VIDEO_SCALE_NEAREST,
|
GST_VIDEO_SCALE_NEAREST,
|
||||||
GST_VIDEO_SCALE_BILINEAR,
|
GST_VIDEO_SCALE_BILINEAR,
|
||||||
GST_VIDEO_SCALE_4TAP
|
GST_VIDEO_SCALE_4TAP,
|
||||||
|
GST_VIDEO_SCALE_LANCZOS
|
||||||
} GstVideoScaleMethod;
|
} GstVideoScaleMethod;
|
||||||
|
|
||||||
typedef struct _GstVideoScale GstVideoScale;
|
typedef struct _GstVideoScale GstVideoScale;
|
||||||
|
@ -67,8 +69,14 @@ typedef struct _GstVideoScaleClass GstVideoScaleClass;
|
||||||
struct _GstVideoScale {
|
struct _GstVideoScale {
|
||||||
GstVideoFilter element;
|
GstVideoFilter element;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
GstVideoScaleMethod method;
|
GstVideoScaleMethod method;
|
||||||
gboolean add_borders;
|
gboolean add_borders;
|
||||||
|
double sharpness;
|
||||||
|
double sharpen;
|
||||||
|
gboolean dither;
|
||||||
|
int submethod;
|
||||||
|
double envelope;
|
||||||
|
|
||||||
/* negotiated stuff */
|
/* negotiated stuff */
|
||||||
GstVideoFormat format;
|
GstVideoFormat format;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#ifndef __VS_IMAGE_H__
|
#ifndef __VS_IMAGE_H__
|
||||||
#define __VS_IMAGE_H__
|
#define __VS_IMAGE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
#include <_stdint.h>
|
#include <_stdint.h>
|
||||||
|
|
||||||
typedef struct _VSImage VSImage;
|
typedef struct _VSImage VSImage;
|
||||||
|
@ -48,6 +49,9 @@ void vs_image_scale_nearest_RGBA (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
|
void vs_image_scale_lanczos_AYUV (const VSImage * dest, const VSImage * src,
|
||||||
|
uint8_t * tmpbuf, double sharpness, gboolean dither, int submethod,
|
||||||
|
double a, double sharpen);
|
||||||
|
|
||||||
void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
|
@ -68,6 +72,9 @@ void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
|
void vs_image_scale_lanczos_Y (const VSImage *dest, const VSImage *src,
|
||||||
|
uint8_t *tmpbuf, double sharpness, gboolean dither, int submethod,
|
||||||
|
double a, double sharpen);
|
||||||
|
|
||||||
void vs_image_scale_nearest_RGB565 (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_nearest_RGB565 (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
|
|
1558
gst/videoscale/vs_lanczos.c
Normal file
1558
gst/videoscale/vs_lanczos.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue