/*#define DEBUG_ENABLED */
#include <gstvideoscale.h>
+#include <videoscale.h>
/* 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)
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 }; */
}
-/*
-static GstPadNegotiateReturn
-videoscale_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+static GstPadTemplate *
+gst_videoscale_src_template_factory(void)
+{
+ static GstPadTemplate *templ = NULL;
+
+ 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));
+
+ 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)
{
- 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("sink","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_SINK, GST_PAD_ALWAYS, caps);
}
+ return templ;
+}
- *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)
- );
+static GstCaps *
+gst_videoscale_get_capslist(void)
+{
+ static GstCaps *capslist = NULL;
+ GstCaps *caps;
+ int i;
+
+ if (capslist){
+ gst_caps_ref(capslist);
+ return capslist;
+ }
- return GST_PAD_NEGOTIATE_AGREE;
+ for(i=0;i<videoscale_n_formats;i++){
+ caps = videoscale_get_caps(videoscale_formats + i);
+ capslist = gst_caps_append(capslist, caps);
+ }
+
+ gst_caps_ref(capslist);
+ return capslist;
}
-static GstPadNegotiateReturn
-videoscale_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+static GstCaps *
+gst_videoscale_getcaps (GstPad *pad, GstCaps *caps)
{
- GST_DEBUG(0,"videoscale_negotiate_sink");
+ GstVideoscale *videoscale;
+ GstCaps *capslist = NULL;
+ GstCaps *peercaps;
+ GstCaps *sizecaps;
+ int i;
- if (*caps==NULL)
- return GST_PAD_NEGOTIATE_FAIL;
+ GST_DEBUG(0,"gst_videoscale_src_link");
+ videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
- return GST_PAD_NEGOTIATE_AGREE;
+ /* 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_sinkconnect (GstPad *pad, GstCaps *caps)
+gst_videoscale_src_link (GstPad *pad, GstCaps *caps)
{
GstVideoscale *videoscale;
+ GstPadLinkReturn ret;
+ GstCaps *peercaps;
- GST_DEBUG(0,"gst_videoscale_sinkconnect");
+ 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",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)
- ));
+ GST_DEBUG(0,"width %d height %d",videoscale->to_width,videoscale->to_height);
+
+ 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
{
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; */
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
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);
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);
&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));
*/
#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"
#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);
+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)
+{
+ 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));
+ }
+
+ return caps;
+}
+
+struct videoscale_format_struct *
+videoscale_find_by_caps(GstCaps *caps)
+{
+ 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 *scale)
+gst_videoscale_setup (GstVideoscale *videoscale)
{
- 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 */
+ 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;
}
- 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 */
+ 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;
}
- return; /* XXX */
+ 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 *src, unsigned char *dest)
+gst_videoscale_scale_rgb (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 RGB %dx%d to %dx%d", sw, sh, dw, dh);
switch (scale->scale_bytes) {
}
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;
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))
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)
}
}
}
+#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)
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;
xpos = 0x10000;
- switch (scale->scale_bytes) {
- case 4:
- {
- guint32 *destp = (guint32 *)dest;
- guint32 *srcp = (guint32 *)src;
-
- for ( x=dw>>2; x; x-- ) {
- while ( xpos >= 0x10000L ) {
- srcp++;
- xpos -= 0x10000L;
- }
- *destp++ = *srcp;
- xpos += xinc;
- }
- break;
+ srcp = src;
+ destp = dest;
+
+ for ( x=dw; x; x-- ) {
+ while ( xpos >= 0x10000L ) {
+ srcp++;
+ xpos -= 0x10000L;
}
- 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;
+ *destp++ = *srcp;
+ xpos += xinc;
+ }
+ dest += dw;
+
+ ypos += yinc;
+ }
+}
+
+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;
}
- case 1:
- {
- guchar *destp = dest;
- guchar *srcp = src;
-
- for ( x=dw; x; x-- ) {
- while ( xpos >= 0x10000L ) {
- srcp++;
- xpos -= 0x10000L;
- }
- *destp++ = *srcp;
- xpos += xinc;
- }
+ *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;
+ 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;
}