Rewrote much of videoscale. Now handles most common YUV formats as well as 32 and 24 bit RGB. Only handles "nearest...

Original commit message from CVS:
Rewrote much of videoscale.  Now handles most common YUV formats
as well as 32 and 24 bit RGB.  Only handles "nearest" scaling.
This commit is contained in:
David Schleef 2003-04-22 07:32:50 +00:00
parent 9cd5e80245
commit 856cea1d53
4 changed files with 686 additions and 221 deletions

View file

@ -20,6 +20,7 @@
/*#define DEBUG_ENABLED */
#include <gstvideoscale.h>
#include <videoscale.h>
@ -48,28 +49,6 @@ enum {
/* FILL ME */
};
GST_PAD_TEMPLATE_FACTORY (sink_templ,
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"videoscale_caps",
"video/raw",
"format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0'))
)
)
GST_PAD_TEMPLATE_FACTORY (src_templ,
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_CAPS_NEW (
"videoscale_caps",
"video/raw",
"format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0'))
)
)
#define GST_TYPE_VIDEOSCALE_METHOD (gst_videoscale_method_get_type())
static GType
gst_videoscale_method_get_type (void)
@ -95,6 +74,7 @@ static void gst_videoscale_set_property (GObject *object, guint prop_id, const
static void gst_videoscale_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void gst_videoscale_chain (GstPad *pad, GstBuffer *buf);
static GstCaps * gst_videoscale_get_capslist(void);
static GstElementClass *parent_class = NULL;
/*static guint gst_videoscale_signals[LAST_SIGNAL] = { 0 }; */
@ -146,70 +126,189 @@ gst_videoscale_class_init (GstVideoscaleClass *klass)
}
/*
static GstPadNegotiateReturn
videoscale_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
static GstPadTemplate *
gst_videoscale_src_template_factory(void)
{
GstVideoscale *videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
static GstPadTemplate *templ = NULL;
GST_DEBUG(0,"videoscale_negotiate_src");
if(!templ){
GstCaps *caps = GST_CAPS_NEW("src","video/raw",
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT));
if(*caps==NULL){
return GST_PAD_NEGOTIATE_FAIL;
caps = gst_caps_intersect(caps, gst_videoscale_get_capslist ());
templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
}
return templ;
}
static GstPadTemplate *
gst_videoscale_sink_template_factory(void)
{
static GstPadTemplate *templ = NULL;
if(!templ){
GstCaps *caps = GST_CAPS_NEW("sink","video/raw",
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT));
caps = gst_caps_intersect(caps, gst_videoscale_get_capslist ());
templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
}
return templ;
}
static GstCaps *
gst_videoscale_get_capslist(void)
{
static GstCaps *capslist = NULL;
GstCaps *caps;
int i;
if (capslist){
gst_caps_ref(capslist);
return capslist;
}
*caps = GST_CAPS_NEW ( "videoscale_caps",
"video/raw",
"format", GST_PROPS_FOURCC (videoscale->format),
"width", GST_PROPS_INT (videoscale->targetwidth),
"height", GST_PROPS_INT (videoscale->targetheight)
);
for(i=0;i<videoscale_n_formats;i++){
caps = videoscale_get_caps(videoscale_formats + i);
capslist = gst_caps_append(capslist, caps);
}
return GST_PAD_NEGOTIATE_AGREE;
gst_caps_ref(capslist);
return capslist;
}
static GstPadNegotiateReturn
videoscale_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
{
GST_DEBUG(0,"videoscale_negotiate_sink");
if (*caps==NULL)
return GST_PAD_NEGOTIATE_FAIL;
return GST_PAD_NEGOTIATE_AGREE;
}
*/
static GstPadLinkReturn
gst_videoscale_sinkconnect (GstPad *pad, GstCaps *caps)
static GstCaps *
gst_videoscale_getcaps (GstPad *pad, GstCaps *caps)
{
GstVideoscale *videoscale;
GstCaps *capslist = NULL;
GstCaps *peercaps;
GstCaps *sizecaps;
int i;
GST_DEBUG(0,"gst_videoscale_sinkconnect");
GST_DEBUG(0,"gst_videoscale_src_link");
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
/* get list of peer's caps */
if(pad == videoscale->srcpad){
peercaps = gst_pad_get_allowed_caps (videoscale->sinkpad);
}else{
peercaps = gst_pad_get_allowed_caps (videoscale->srcpad);
}
/* FIXME videoscale doesn't allow passthru of video formats it
* doesn't understand. */
/* Look through our list of caps and find those that match with
* the peer's formats. Create a list of them. */
for(i=0;i<videoscale_n_formats;i++){
GstCaps *fromcaps = videoscale_get_caps(videoscale_formats + i);
if(gst_caps_is_always_compatible(fromcaps, peercaps)){
capslist = gst_caps_append(capslist, fromcaps);
}
gst_caps_unref (fromcaps);
}
gst_caps_unref (peercaps);
sizecaps = GST_CAPS_NEW("videoscale_size","video/raw",
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
"height", GST_PROPS_INT_RANGE (0, G_MAXINT));
caps = gst_caps_intersect(caps, gst_videoscale_get_capslist ());
gst_caps_unref (sizecaps);
return caps;
}
static GstPadLinkReturn
gst_videoscale_src_link (GstPad *pad, GstCaps *caps)
{
GstVideoscale *videoscale;
GstPadLinkReturn ret;
GstCaps *peercaps;
GST_DEBUG(0,"gst_videoscale_src_link");
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
if (!GST_CAPS_IS_FIXED (caps)) {
return GST_PAD_LINK_DELAYED;
}
gst_caps_get_fourcc_int (caps, "format", &videoscale->format);
gst_caps_get_int (caps, "width", &videoscale->width);
gst_caps_get_int (caps, "height", &videoscale->height);
videoscale->format = videoscale_find_by_caps (caps);
gst_caps_get_int (caps, "width", &videoscale->to_width);
gst_caps_get_int (caps, "height", &videoscale->to_height);
gst_videoscale_setup(videoscale);
GST_DEBUG (0,"target size %d x %d",videoscale->targetwidth,
videoscale->targetheight);
GST_DEBUG(0,"width %d height %d",videoscale->to_width,videoscale->to_height);
GST_DEBUG(0,"width %d",videoscale->targetwidth);
return gst_pad_try_set_caps (videoscale->srcpad,
GST_CAPS_NEW (
"videoscale_src",
"video/raw",
"format", GST_PROPS_FOURCC (videoscale->format),
"width", GST_PROPS_INT (videoscale->targetwidth),
"height", GST_PROPS_INT (videoscale->targetheight)
));
peercaps = gst_caps_copy(caps);
gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT));
gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT));
ret = gst_pad_try_set_caps (videoscale->srcpad, peercaps);
gst_caps_unref(peercaps);
if(ret==GST_PAD_LINK_OK){
caps = gst_pad_get_caps (videoscale->srcpad);
gst_caps_get_int (caps, "width", &videoscale->from_width);
gst_caps_get_int (caps, "height", &videoscale->from_height);
gst_videoscale_setup(videoscale);
}
return ret;
}
static GstPadLinkReturn
gst_videoscale_sink_link (GstPad *pad, GstCaps *caps)
{
GstVideoscale *videoscale;
GstPadLinkReturn ret;
GstCaps *peercaps;
GST_DEBUG(0,"gst_videoscale_src_link");
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
if (!GST_CAPS_IS_FIXED (caps)) {
return GST_PAD_LINK_DELAYED;
}
videoscale->format = videoscale_find_by_caps (caps);
gst_caps_get_int (caps, "width", &videoscale->from_width);
gst_caps_get_int (caps, "height", &videoscale->from_height);
gst_videoscale_setup(videoscale);
peercaps = gst_caps_copy(caps);
if(videoscale->force_size){
gst_caps_set(peercaps, "width", GST_PROPS_INT (videoscale->forced_width));
gst_caps_set(peercaps, "height", GST_PROPS_INT (videoscale->forced_height));
}else{
gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT));
gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT));
}
ret = gst_pad_try_set_caps (videoscale->srcpad, peercaps);
gst_caps_unref(peercaps);
if(ret==GST_PAD_LINK_OK){
caps = gst_pad_get_caps (videoscale->srcpad);
gst_caps_get_int (caps, "width", &videoscale->to_width);
gst_caps_get_int (caps, "height", &videoscale->to_height);
gst_videoscale_setup(videoscale);
}
return ret;
}
static void
@ -217,19 +316,23 @@ gst_videoscale_init (GstVideoscale *videoscale)
{
GST_DEBUG(0,"gst_videoscale_init");
videoscale->sinkpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (sink_templ), "sink");
/*gst_pad_set_negotiate_function(videoscale->sinkpad,videoscale_negotiate_sink); */
GST_PAD_TEMPLATE_GET (gst_videoscale_sink_template_factory),
"sink");
gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->sinkpad);
gst_pad_set_chain_function(videoscale->sinkpad,gst_videoscale_chain);
gst_pad_set_link_function(videoscale->sinkpad,gst_videoscale_sinkconnect);
gst_pad_set_link_function(videoscale->sinkpad,gst_videoscale_sink_link);
gst_pad_set_getcaps_function(videoscale->sinkpad,gst_videoscale_getcaps);
videoscale->srcpad = gst_pad_new_from_template (
GST_PAD_TEMPLATE_GET (src_templ), "src");
/*gst_pad_set_negotiate_function(videoscale->srcpad,videoscale_negotiate_src); */
GST_PAD_TEMPLATE_GET (gst_videoscale_src_template_factory),
"src");
gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->srcpad);
gst_pad_set_link_function(videoscale->srcpad,gst_videoscale_src_link);
gst_pad_set_getcaps_function(videoscale->srcpad,gst_videoscale_getcaps);
videoscale->inited = FALSE;
videoscale->force_size = FALSE;
videoscale->targetwidth = -1;
videoscale->targetheight = -1;
videoscale->method = GST_VIDEOSCALE_NEAREST;
/*videoscale->method = GST_VIDEOSCALE_BILINEAR; */
/*videoscale->method = GST_VIDEOSCALE_POINT_SAMPLE; */
@ -251,43 +354,46 @@ gst_videoscale_chain (GstPad *pad, GstBuffer *buf)
g_return_if_fail (buf != NULL);
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
g_return_if_fail (videoscale->inited);
data = GST_BUFFER_DATA(buf);
size = GST_BUFFER_SIZE(buf);
if(!videoscale->scale_cc){
gst_caps_get_int (gst_pad_get_caps(pad), "format", &videoscale->format);
gst_videoscale_setup(videoscale);
if(videoscale->passthru){
gst_pad_push(videoscale->srcpad, buf);
return;
}
GST_DEBUG (0,"gst_videoscale_chain: got buffer of %ld bytes in '%s'",size,
GST_OBJECT_NAME (videoscale));
GST_DEBUG(0,"size=%ld from=%dx%d to=%dx%d newsize=%d",
GST_DEBUG(0,"size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d",
size,
videoscale->width, videoscale->height,
videoscale->targetwidth, videoscale->targetheight,
videoscale->targetwidth*videoscale->targetheight + videoscale->targetwidth*videoscale->targetheight/2);
videoscale->from_width, videoscale->from_height,
videoscale->to_width, videoscale->to_height,
size, videoscale->from_buf_size,
videoscale->to_buf_size);
if(videoscale->targetwidth==videoscale->width &&
videoscale->targetheight==videoscale->height){
gst_pad_push(videoscale->srcpad, buf);
}else{
outbuf = gst_buffer_new();
/* XXX this is wrong for anything but I420 */
GST_BUFFER_SIZE(outbuf) = videoscale->targetwidth*videoscale->targetheight +
videoscale->targetwidth*videoscale->targetheight/2;
GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->targetwidth*videoscale->targetheight*2);
GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
g_return_if_fail (size == videoscale->from_buf_size);
/*g_return_if_fail(videoscale->scale_cc != NULL); */
videoscale->scale_cc(videoscale, data, GST_BUFFER_DATA(outbuf));
outbuf = gst_buffer_new();
/* FIXME: handle bufferpools */
GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size;
GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size);
GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
GST_DEBUG (0,"gst_videoscale_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf),
GST_OBJECT_NAME (videoscale));
g_return_if_fail(videoscale->format);
GST_DEBUG (0,"format %s",videoscale->format->fourcc);
g_return_if_fail(videoscale->format->scale);
gst_pad_push(videoscale->srcpad, outbuf);
videoscale->format->scale(videoscale, GST_BUFFER_DATA(outbuf), data);
gst_buffer_unref(buf);
}
GST_DEBUG (0,"gst_videoscale_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf),
GST_OBJECT_NAME (videoscale));
gst_pad_push(videoscale->srcpad, outbuf);
gst_buffer_unref(buf);
}
static void
@ -302,10 +408,12 @@ gst_videoscale_set_property (GObject *object, guint prop_id, const GValue *value
GST_DEBUG(0,"gst_videoscale_set_property");
switch (prop_id) {
case ARG_WIDTH:
src->targetwidth = g_value_get_int (value);
src->forced_width = g_value_get_int (value);
src->force_size = TRUE;
break;
case ARG_HEIGHT:
src->targetheight = g_value_get_int (value);
src->forced_height = g_value_get_int (value);
src->force_size = TRUE;
break;
case ARG_METHOD:
src->method = g_value_get_enum (value);
@ -326,10 +434,10 @@ gst_videoscale_get_property (GObject *object, guint prop_id, GValue *value, GPar
switch (prop_id) {
case ARG_WIDTH:
g_value_set_int (value, src->targetwidth);
g_value_set_int (value, src->forced_width);
break;
case ARG_HEIGHT:
g_value_set_int (value, src->targetheight);
g_value_set_int (value, src->forced_height);
break;
case ARG_METHOD:
g_value_set_enum (value, src->method);
@ -351,8 +459,8 @@ plugin_init (GModule *module, GstPlugin *plugin)
&videoscale_details);
g_return_val_if_fail(factory != NULL, FALSE);
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_templ));
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_templ));
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videoscale_sink_template_factory));
gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (gst_videoscale_src_template_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));

View file

@ -57,21 +57,29 @@ struct _GstVideoscale {
GstPad *sinkpad,*srcpad;
gboolean force_size;
gint forced_width;
gint forced_height;
/* video state */
guint32 format;
gint width;
gint height;
gint targetwidth;
gint targetheight;
gboolean inited;
struct videoscale_format_struct *format;
gint to_width;
gint to_height;
gint from_width;
gint from_height;
gboolean passthru;
GstVideoScaleMethod method;
guint scale_bytes;
/* private */
gint from_buf_size;
gint to_buf_size;
#if 0
guchar *temp;
void (*scale_cc) (GstVideoscale *scale, guchar *src, guchar *dest);
void (*scaler) (GstVideoscale *scale, guchar *src, guchar *dest,int,int,int,int);
guchar (*filter) (guchar *src, gdouble x, gdouble y, gint sw, gint sh);
guchar copy_row[8192];
#endif
};
struct _GstVideoscaleClass {

View file

@ -18,8 +18,11 @@
*/
#define DEBUG_ENABLED
#include <gst/gst.h>
#include <stdlib.h>
#include <math.h>
#include <videoscale.h>
#include <string.h>
#include "config.h"
#include "gstvideoscale.h"
@ -28,79 +31,152 @@
#include "videoscale_x86.h"
#endif
static void gst_videoscale_scale_yuv (GstVideoscale *scale, unsigned char *src, unsigned char *dest);
static void gst_videoscale_scale_rgb (GstVideoscale *scale, unsigned char *src, unsigned char *dest);
/* scalers */
static void gst_videoscale_scale_nearest (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
static void gst_videoscale_scale_nearest (GstVideoscale *scale, unsigned char *dest, unsigned char *src,
int sw, int sh, int dw, int dh);
#if 0
static void gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
int sw, int sh, int dw, int dh);
static void gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
int sw, int sh, int dw, int dh);
#endif
/* filters */
static unsigned char gst_videoscale_bilinear (unsigned char *src, double x, double y, int sw, int sh);
static unsigned char gst_videoscale_bicubic (unsigned char *src, double x, double y, int sw, int sh);
void
gst_videoscale_setup (GstVideoscale *scale)
static void gst_videoscale_planar411 (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_planar400 (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_packed422 (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_packed422rev (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_32bit (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_24bit (GstVideoscale *scale, unsigned char *dest, unsigned char *src);
static void gst_videoscale_scale_nearest_str2 (GstVideoscale *scale,
unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh);
static void gst_videoscale_scale_nearest_str4 (GstVideoscale *scale,
unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh);
static void gst_videoscale_scale_nearest_32bit (GstVideoscale *scale,
unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh);
static void gst_videoscale_scale_nearest_24bit (GstVideoscale *scale,
unsigned char *dest, unsigned char *src, int sw, int sh, int dw, int dh);
struct videoscale_format_struct videoscale_formats[] = {
/* packed */
{ "YUY2", 16, gst_videoscale_packed422, },
{ "UYVY", 16, gst_videoscale_packed422rev, },
{ "Y422", 16, gst_videoscale_packed422rev, },
{ "UYNV", 16, gst_videoscale_packed422rev, },
{ "YVYU", 16, gst_videoscale_packed422, },
/* planar */
{ "YV12", 12, gst_videoscale_planar411, },
{ "I420", 12, gst_videoscale_planar411, },
{ "IYUV", 12, gst_videoscale_planar411, },
{ "Y800", 8, gst_videoscale_planar400, },
{ "Y8 ", 8, gst_videoscale_planar400, },
/* RGB */
{ "RGB ", 32, gst_videoscale_32bit, 24, G_BIG_ENDIAN, 0x00ff0000, 0x0000ff00, 0x000000ff },
{ "RGB ", 32, gst_videoscale_32bit, 24, G_BIG_ENDIAN, 0x000000ff, 0x0000ff00, 0x00ff0000 },
{ "RGB ", 32, gst_videoscale_32bit, 24, G_BIG_ENDIAN, 0xff000000, 0x00ff0000, 0x0000ff00 },
{ "RGB ", 32, gst_videoscale_32bit, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000, 0xff000000 },
{ "RGB ", 24, gst_videoscale_24bit, 24, G_BIG_ENDIAN, 0xff0000, 0x00ff00, 0x0000ff },
{ "RGB ", 24, gst_videoscale_24bit, 24, G_BIG_ENDIAN, 0x0000ff, 0x00ff00, 0xff0000 },
};
int videoscale_n_formats = sizeof(videoscale_formats)/sizeof(videoscale_formats[0]);
GstCaps *
videoscale_get_caps(struct videoscale_format_struct *format)
{
switch (scale->format) {
case GST_MAKE_FOURCC('I','4','2','0'):
scale->scale_cc = gst_videoscale_scale_yuv;
scale->scale_bytes = 1;
break;
case GST_MAKE_FOURCC('R','G','B',' '):
scale->scale_cc = gst_videoscale_scale_rgb;
/* XXX */
/*scale->scale_bytes = gst_caps_get_int(scale->srcpad->caps,"bpp")/8; */
break;
default:
g_print("videoscale: unsupported video format %08x\n", scale->format);
return; /* XXX */
unsigned int fourcc;
GstCaps *caps;
if(format->scale==NULL)
return NULL;
fourcc = GST_MAKE_FOURCC(format->fourcc[0],format->fourcc[1],format->fourcc[2],format->fourcc[3]);
if(format->bpp){
caps = GST_CAPS_NEW ("videoscale", "video/raw",
"format", GST_PROPS_FOURCC (fourcc),
"depth", GST_PROPS_INT(format->bpp),
"bpp", GST_PROPS_INT(format->depth),
"endianness", GST_PROPS_INT(format->endianness),
"red_mask", GST_PROPS_INT(format->red_mask),
"green_mask", GST_PROPS_INT(format->green_mask),
"blue_mask", GST_PROPS_INT(format->blue_mask));
}else{
caps = GST_CAPS_NEW ("videoscale", "video/raw",
"format", GST_PROPS_FOURCC (fourcc));
}
switch (scale->method) {
case GST_VIDEOSCALE_POINT_SAMPLE:
scale->scaler = gst_videoscale_scale_point_sample;
GST_DEBUG (0,"videoscale: scaling method POINT_SAMPLE");
break;
case GST_VIDEOSCALE_NEAREST:
#ifdef HAVE_CPU_I386
gst_videoscale_generate_rowbytes_x86 (scale->copy_row, scale->width,
scale->targetwidth, scale->scale_bytes);
scale->scaler = gst_videoscale_scale_nearest_x86;
#else
scale->scaler = gst_videoscale_scale_nearest;
#endif
GST_DEBUG (0,"videoscale: scaling method NEAREST");
break;
case GST_VIDEOSCALE_BILINEAR:
scale->scaler = gst_videoscale_scale_plane_slow;
scale->filter = gst_videoscale_bilinear;
GST_DEBUG (0,"videoscale: scaling method BILINEAR");
break;
case GST_VIDEOSCALE_BICUBIC:
scale->scaler = gst_videoscale_scale_plane_slow;
scale->filter = gst_videoscale_bicubic;
GST_DEBUG (0,"videoscale: scaling method BICUBIC");
break;
default:
g_print("videoscale: unsupported scaling method %d\n", scale->method);
return; /* XXX */
}
return; /* XXX */
return caps;
}
static void
gst_videoscale_scale_rgb (GstVideoscale *scale, unsigned char *src, unsigned char *dest)
struct videoscale_format_struct *
videoscale_find_by_caps(GstCaps *caps)
{
int sw = scale->width;
int sh = scale->height;
int dw = scale->targetwidth;
int dh = scale->targetheight;
int i;
GST_DEBUG (0,"finding %p",caps);
g_return_val_if_fail(caps != NULL, NULL);
for (i = 0; i < videoscale_n_formats; i++){
GstCaps *c;
c = videoscale_get_caps(videoscale_formats + i);
if(c){
if(gst_caps_is_always_compatible(caps, c)){
gst_caps_unref(c);
return videoscale_formats + i;
}
gst_caps_unref(c);
}
}
return NULL;
}
void
gst_videoscale_setup (GstVideoscale *videoscale)
{
GST_DEBUG (0,"format=%p \"%s\" from %dx%d to %dx%d",
videoscale->format, videoscale->format->fourcc,
videoscale->from_width, videoscale->from_height,
videoscale->to_width, videoscale->to_height);
if(videoscale->to_width==0 || videoscale->to_height==0 ||
videoscale->from_width==0 || videoscale->from_height==0){
return;
}
if(videoscale->to_width == videoscale->from_width &&
videoscale->to_height == videoscale->from_height){
GST_DEBUG (0,"videoscale: using passthru");
videoscale->passthru = TRUE;
videoscale->inited = TRUE;
return;
}
GST_DEBUG (0,"videoscale: scaling method POINT_SAMPLE");
videoscale->from_buf_size = (videoscale->from_width * videoscale->from_height
* videoscale->format->depth) / 8;
videoscale->to_buf_size = (videoscale->to_width * videoscale->to_height
* videoscale->format->depth) / 8;
videoscale->inited = TRUE;
}
#if 0
static void
gst_videoscale_scale_rgb (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling RGB %dx%d to %dx%d", sw, sh, dw, dh);
switch (scale->scale_bytes) {
@ -117,20 +193,21 @@ gst_videoscale_scale_rgb (GstVideoscale *scale, unsigned char *src, unsigned cha
}
GST_DEBUG (0,"videoscale: %p %p", src, dest);
scale->scaler(scale, src, dest, sw, sh, dw, dh);
//scale->scaler(scale, src, dest, sw, sh, dw, dh);
}
#endif
static void
gst_videoscale_scale_yuv (GstVideoscale *scale, unsigned char *src, unsigned char *dest)
gst_videoscale_planar411 (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->width;
int sh = scale->height;
int dw = scale->targetwidth;
int dh = scale->targetheight;
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling YUV420P %dx%d to %dx%d", sw, sh, dw, dh);
GST_DEBUG (0,"videoscale: scaling planar 4:1:1 %dx%d to %dx%d", sw, sh, dw, dh);
scale->scaler(scale, src, dest, sw, sh, dw, dh);
gst_videoscale_scale_nearest(scale, dest, src, sw, sh, dw, dh);
src += sw*sh;
dest += dw*dh;
@ -140,12 +217,85 @@ gst_videoscale_scale_yuv (GstVideoscale *scale, unsigned char *src, unsigned cha
sh = sh>>1;
sw = sw>>1;
scale->scaler(scale, src, dest, sw, sh, dw, dh);
gst_videoscale_scale_nearest(scale, dest, src, sw, sh, dw, dh);
src += sw*sh;
dest += dw*dh;
scale->scaler(scale, src, dest, sw, sh, dw, dh);
gst_videoscale_scale_nearest(scale, dest, src, sw, sh, dw, dh);
}
static void
gst_videoscale_planar400 (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling Y-only %dx%d to %dx%d", sw, sh, dw, dh);
gst_videoscale_scale_nearest(scale, dest, src, sw, sh, dw, dh);
}
static void
gst_videoscale_packed422 (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling 4:2:2 %dx%d to %dx%d", sw, sh, dw, dh);
gst_videoscale_scale_nearest_str2(scale, dest, src, sw, sh, dw, dh);
gst_videoscale_scale_nearest_str4(scale, dest+1, src+1, sw/2, sh, dw/2, dh);
gst_videoscale_scale_nearest_str4(scale, dest+3, src+3, sw/2, sh, dw/2, dh);
}
static void
gst_videoscale_packed422rev (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling 4:2:2 %dx%d to %dx%d", sw, sh, dw, dh);
gst_videoscale_scale_nearest_str2(scale, dest+1, src, sw, sh, dw, dh);
gst_videoscale_scale_nearest_str4(scale, dest, src+1, sw/2, sh, dw/2, dh);
gst_videoscale_scale_nearest_str4(scale, dest+2, src+3, sw/2, sh, dw/2, dh);
}
static void
gst_videoscale_32bit (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling 32bit %dx%d to %dx%d", sw, sh, dw, dh);
gst_videoscale_scale_nearest_32bit(scale, dest, src, sw, sh, dw, dh);
}
static void
gst_videoscale_24bit (GstVideoscale *scale, unsigned char *dest, unsigned char *src)
{
int sw = scale->from_width;
int sh = scale->from_height;
int dw = scale->to_width;
int dh = scale->to_height;
GST_DEBUG (0,"videoscale: scaling 24bit %dx%d to %dx%d", sw, sh, dw, dh);
gst_videoscale_scale_nearest_24bit(scale, dest, src, sw, sh, dw, dh);
}
#define RC(x,y) *(src+(int)(x)+(int)((y)*sw))
@ -213,6 +363,7 @@ gst_videoscale_bicubic (unsigned char *src, double x, double y, int sw, int sh)
return (unsigned char) color;
}
#if 0
static void
gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
int sw, int sh, int dw, int dh)
@ -242,7 +393,9 @@ gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsig
}
}
}
#endif
#if 0
static void
gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
int sw, int sh, int dw, int dh)
@ -290,17 +443,20 @@ gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, uns
ypos += yinc;
}
}
#endif
static void
gst_videoscale_scale_nearest (GstVideoscale *scale,
unsigned char *src,
unsigned char *dest,
unsigned char *src,
int sw, int sh, int dw, int dh)
{
int ypos, yinc, y;
int xpos, xinc, x;
guchar *destp = dest;
guchar *srcp = src;
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d %d", src, dest, dw, scale->scale_bytes);
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d", src, dest, dw);
ypos = 0x10000;
@ -316,51 +472,16 @@ gst_videoscale_scale_nearest (GstVideoscale *scale,
xpos = 0x10000;
switch (scale->scale_bytes) {
case 4:
{
guint32 *destp = (guint32 *)dest;
guint32 *srcp = (guint32 *)src;
srcp = src;
destp = dest;
for ( x=dw>>2; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp++;
xpos -= 0x10000L;
}
*destp++ = *srcp;
xpos += xinc;
}
break;
}
case 2:
{
guint16 *destp = (guint16 *)dest;
guint16 *srcp = (guint16 *)src;
for ( x=dw>>1; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp++;
xpos -= 0x10000L;
}
*destp++ = *srcp;
xpos += xinc;
}
break;
}
case 1:
{
guchar *destp = dest;
guchar *srcp = src;
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp++;
xpos -= 0x10000L;
}
*destp++ = *srcp;
xpos += xinc;
}
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp++;
xpos -= 0x10000L;
}
*destp++ = *srcp;
xpos += xinc;
}
dest += dw;
@ -368,3 +489,185 @@ gst_videoscale_scale_nearest (GstVideoscale *scale,
}
}
static void
gst_videoscale_scale_nearest_str2 (GstVideoscale *scale,
unsigned char *dest,
unsigned char *src,
int sw, int sh, int dw, int dh)
{
int ypos, yinc, y;
int xpos, xinc, x;
guchar *destp = dest;
guchar *srcp = src;
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d", src, dest, dw);
ypos = 0x10000;
yinc = (sh<<16)/dh;
xinc = (sw<<16)/dw;
for (y = dh; y; y--) {
while (ypos >0x10000) {
ypos-=0x10000;
src += sw*2;
}
xpos = 0x10000;
srcp = src;
destp = dest;
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp+=2;
xpos -= 0x10000L;
}
*destp = *srcp;
destp+=2;
xpos += xinc;
}
dest += dw*2;
ypos += yinc;
}
}
static void
gst_videoscale_scale_nearest_str4 (GstVideoscale *scale,
unsigned char *dest,
unsigned char *src,
int sw, int sh, int dw, int dh)
{
int ypos, yinc, y;
int xpos, xinc, x;
guchar *destp = dest;
guchar *srcp = src;
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d", src, dest, dw);
ypos = 0x10000;
yinc = (sh<<16)/dh;
xinc = (sw<<16)/dw;
for (y = dh; y; y--) {
while (ypos >0x10000) {
ypos-=0x10000;
src += sw*4;
}
xpos = 0x10000;
srcp = src;
destp = dest;
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp+=4;
xpos -= 0x10000L;
}
*destp = *srcp;
destp+=4;
xpos += xinc;
}
dest += dw*4;
ypos += yinc;
}
}
static void
gst_videoscale_scale_nearest_32bit (GstVideoscale *scale,
unsigned char *dest,
unsigned char *src,
int sw, int sh, int dw, int dh)
{
int ypos, yinc, y;
int xpos, xinc, x;
guchar *destp = dest;
guchar *srcp = src;
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d", src, dest, dw);
ypos = 0x10000;
yinc = (sh<<16)/dh;
xinc = (sw<<16)/dw;
for (y = dh; y; y--) {
while (ypos >0x10000) {
ypos-=0x10000;
src += sw*4;
}
xpos = 0x10000;
srcp = src;
destp = dest;
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp+=4;
xpos -= 0x10000L;
}
*(guint32 *)destp = *(guint32 *)srcp;
destp+=4;
xpos += xinc;
}
dest += dw*4;
ypos += yinc;
}
}
static void
gst_videoscale_scale_nearest_24bit (GstVideoscale *scale,
unsigned char *dest,
unsigned char *src,
int sw, int sh, int dw, int dh)
{
int ypos, yinc, y;
int xpos, xinc, x;
guchar *destp = dest;
guchar *srcp = src;
GST_DEBUG (0, "videoscale: scaling nearest %p %p %d", src, dest, dw);
ypos = 0x10000;
yinc = (sh<<16)/dh;
xinc = (sw<<16)/dw;
for (y = dh; y; y--) {
while (ypos >0x10000) {
ypos-=0x10000;
src += sw*3;
}
xpos = 0x10000;
srcp = src;
destp = dest;
for ( x=dw; x; x-- ) {
while ( xpos >= 0x10000L ) {
srcp+=3;
xpos -= 0x10000L;
}
destp[0] = srcp[0];
destp[1] = srcp[1];
destp[2] = srcp[2];
destp+=3;
xpos += xinc;
}
dest += dw*3;
ypos += yinc;
}
}

View file

@ -0,0 +1,46 @@
/* GStreamer
* Copyright (C) <2003> David A. Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __VIDEOSCALE_H__
#define __VIDEOSCALE_H__
#include "gstvideoscale.h"
struct videoscale_format_struct {
char *fourcc;
int depth;
void (*scale)(GstVideoscale *,unsigned char *dest, unsigned char *src);
int bpp;
unsigned int endianness;
unsigned int red_mask;
unsigned int green_mask;
unsigned int blue_mask;
};
extern struct videoscale_format_struct videoscale_formats[];
extern int videoscale_n_formats;
GstCaps *videoscale_get_caps(struct videoscale_format_struct *format);
struct videoscale_format_struct *videoscale_find_by_caps(GstCaps *caps);
#endif