mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
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:
parent
9cd5e80245
commit
856cea1d53
4 changed files with 686 additions and 221 deletions
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
/*#define DEBUG_ENABLED */
|
/*#define DEBUG_ENABLED */
|
||||||
#include <gstvideoscale.h>
|
#include <gstvideoscale.h>
|
||||||
|
#include <videoscale.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,28 +49,6 @@ enum {
|
||||||
/* FILL ME */
|
/* 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())
|
#define GST_TYPE_VIDEOSCALE_METHOD (gst_videoscale_method_get_type())
|
||||||
static GType
|
static GType
|
||||||
gst_videoscale_method_get_type (void)
|
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_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||||
|
|
||||||
static void gst_videoscale_chain (GstPad *pad, GstBuffer *buf);
|
static void gst_videoscale_chain (GstPad *pad, GstBuffer *buf);
|
||||||
|
static GstCaps * gst_videoscale_get_capslist(void);
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
/*static guint gst_videoscale_signals[LAST_SIGNAL] = { 0 }; */
|
/*static guint gst_videoscale_signals[LAST_SIGNAL] = { 0 }; */
|
||||||
|
@ -146,70 +126,189 @@ gst_videoscale_class_init (GstVideoscaleClass *klass)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static GstPadTemplate *
|
||||||
static GstPadNegotiateReturn
|
gst_videoscale_src_template_factory(void)
|
||||||
videoscale_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
|
||||||
{
|
{
|
||||||
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){
|
caps = gst_caps_intersect(caps, gst_videoscale_get_capslist ());
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
|
||||||
|
templ = GST_PAD_TEMPLATE_NEW("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
|
||||||
|
}
|
||||||
|
return templ;
|
||||||
}
|
}
|
||||||
|
|
||||||
*caps = GST_CAPS_NEW ( "videoscale_caps",
|
static GstPadTemplate *
|
||||||
"video/raw",
|
gst_videoscale_sink_template_factory(void)
|
||||||
"format", GST_PROPS_FOURCC (videoscale->format),
|
|
||||||
"width", GST_PROPS_INT (videoscale->targetwidth),
|
|
||||||
"height", GST_PROPS_INT (videoscale->targetheight)
|
|
||||||
);
|
|
||||||
|
|
||||||
return GST_PAD_NEGOTIATE_AGREE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstPadNegotiateReturn
|
|
||||||
videoscale_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
|
||||||
{
|
{
|
||||||
GST_DEBUG(0,"videoscale_negotiate_sink");
|
static GstPadTemplate *templ = NULL;
|
||||||
|
|
||||||
if (*caps==NULL)
|
if(!templ){
|
||||||
return GST_PAD_NEGOTIATE_FAIL;
|
GstCaps *caps = GST_CAPS_NEW("sink","video/raw",
|
||||||
|
"width", GST_PROPS_INT_RANGE (0, G_MAXINT),
|
||||||
|
"height", GST_PROPS_INT_RANGE (0, G_MAXINT));
|
||||||
|
|
||||||
return GST_PAD_NEGOTIATE_AGREE;
|
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 GstPadLinkReturn
|
static GstCaps *
|
||||||
gst_videoscale_sinkconnect (GstPad *pad, GstCaps *caps)
|
gst_videoscale_get_capslist(void)
|
||||||
|
{
|
||||||
|
static GstCaps *capslist = NULL;
|
||||||
|
GstCaps *caps;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (capslist){
|
||||||
|
gst_caps_ref(capslist);
|
||||||
|
return capslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 GstCaps *
|
||||||
|
gst_videoscale_getcaps (GstPad *pad, GstCaps *caps)
|
||||||
{
|
{
|
||||||
GstVideoscale *videoscale;
|
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));
|
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
if (!GST_CAPS_IS_FIXED (caps)) {
|
if (!GST_CAPS_IS_FIXED (caps)) {
|
||||||
return GST_PAD_LINK_DELAYED;
|
return GST_PAD_LINK_DELAYED;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_caps_get_fourcc_int (caps, "format", &videoscale->format);
|
videoscale->format = videoscale_find_by_caps (caps);
|
||||||
gst_caps_get_int (caps, "width", &videoscale->width);
|
gst_caps_get_int (caps, "width", &videoscale->to_width);
|
||||||
gst_caps_get_int (caps, "height", &videoscale->height);
|
gst_caps_get_int (caps, "height", &videoscale->to_height);
|
||||||
|
|
||||||
gst_videoscale_setup(videoscale);
|
gst_videoscale_setup(videoscale);
|
||||||
|
|
||||||
GST_DEBUG (0,"target size %d x %d",videoscale->targetwidth,
|
GST_DEBUG(0,"width %d height %d",videoscale->to_width,videoscale->to_height);
|
||||||
videoscale->targetheight);
|
|
||||||
|
|
||||||
GST_DEBUG(0,"width %d",videoscale->targetwidth);
|
peercaps = gst_caps_copy(caps);
|
||||||
return gst_pad_try_set_caps (videoscale->srcpad,
|
|
||||||
GST_CAPS_NEW (
|
gst_caps_set(peercaps, "width", GST_PROPS_INT_RANGE (0, G_MAXINT));
|
||||||
"videoscale_src",
|
gst_caps_set(peercaps, "height", GST_PROPS_INT_RANGE (0, G_MAXINT));
|
||||||
"video/raw",
|
|
||||||
"format", GST_PROPS_FOURCC (videoscale->format),
|
ret = gst_pad_try_set_caps (videoscale->srcpad, peercaps);
|
||||||
"width", GST_PROPS_INT (videoscale->targetwidth),
|
|
||||||
"height", GST_PROPS_INT (videoscale->targetheight)
|
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
|
static void
|
||||||
|
@ -217,19 +316,23 @@ gst_videoscale_init (GstVideoscale *videoscale)
|
||||||
{
|
{
|
||||||
GST_DEBUG(0,"gst_videoscale_init");
|
GST_DEBUG(0,"gst_videoscale_init");
|
||||||
videoscale->sinkpad = gst_pad_new_from_template (
|
videoscale->sinkpad = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (sink_templ), "sink");
|
GST_PAD_TEMPLATE_GET (gst_videoscale_sink_template_factory),
|
||||||
/*gst_pad_set_negotiate_function(videoscale->sinkpad,videoscale_negotiate_sink); */
|
"sink");
|
||||||
gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->sinkpad);
|
gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->sinkpad);
|
||||||
gst_pad_set_chain_function(videoscale->sinkpad,gst_videoscale_chain);
|
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 (
|
videoscale->srcpad = gst_pad_new_from_template (
|
||||||
GST_PAD_TEMPLATE_GET (src_templ), "src");
|
GST_PAD_TEMPLATE_GET (gst_videoscale_src_template_factory),
|
||||||
/*gst_pad_set_negotiate_function(videoscale->srcpad,videoscale_negotiate_src); */
|
"src");
|
||||||
gst_element_add_pad(GST_ELEMENT(videoscale),videoscale->srcpad);
|
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_NEAREST;
|
||||||
/*videoscale->method = GST_VIDEOSCALE_BILINEAR; */
|
/*videoscale->method = GST_VIDEOSCALE_BILINEAR; */
|
||||||
/*videoscale->method = GST_VIDEOSCALE_POINT_SAMPLE; */
|
/*videoscale->method = GST_VIDEOSCALE_POINT_SAMPLE; */
|
||||||
|
@ -251,35 +354,39 @@ gst_videoscale_chain (GstPad *pad, GstBuffer *buf)
|
||||||
g_return_if_fail (buf != NULL);
|
g_return_if_fail (buf != NULL);
|
||||||
|
|
||||||
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
|
videoscale = GST_VIDEOSCALE (gst_pad_get_parent (pad));
|
||||||
|
g_return_if_fail (videoscale->inited);
|
||||||
|
|
||||||
data = GST_BUFFER_DATA(buf);
|
data = GST_BUFFER_DATA(buf);
|
||||||
size = GST_BUFFER_SIZE(buf);
|
size = GST_BUFFER_SIZE(buf);
|
||||||
|
|
||||||
if(!videoscale->scale_cc){
|
if(videoscale->passthru){
|
||||||
gst_caps_get_int (gst_pad_get_caps(pad), "format", &videoscale->format);
|
gst_pad_push(videoscale->srcpad, buf);
|
||||||
gst_videoscale_setup(videoscale);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG (0,"gst_videoscale_chain: got buffer of %ld bytes in '%s'",size,
|
GST_DEBUG (0,"gst_videoscale_chain: got buffer of %ld bytes in '%s'",size,
|
||||||
GST_OBJECT_NAME (videoscale));
|
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,
|
size,
|
||||||
videoscale->width, videoscale->height,
|
videoscale->from_width, videoscale->from_height,
|
||||||
videoscale->targetwidth, videoscale->targetheight,
|
videoscale->to_width, videoscale->to_height,
|
||||||
videoscale->targetwidth*videoscale->targetheight + videoscale->targetwidth*videoscale->targetheight/2);
|
size, videoscale->from_buf_size,
|
||||||
|
videoscale->to_buf_size);
|
||||||
|
|
||||||
|
g_return_if_fail (size == videoscale->from_buf_size);
|
||||||
|
|
||||||
if(videoscale->targetwidth==videoscale->width &&
|
|
||||||
videoscale->targetheight==videoscale->height){
|
|
||||||
gst_pad_push(videoscale->srcpad, buf);
|
|
||||||
}else{
|
|
||||||
outbuf = gst_buffer_new();
|
outbuf = gst_buffer_new();
|
||||||
/* XXX this is wrong for anything but I420 */
|
/* FIXME: handle bufferpools */
|
||||||
GST_BUFFER_SIZE(outbuf) = videoscale->targetwidth*videoscale->targetheight +
|
GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size;
|
||||||
videoscale->targetwidth*videoscale->targetheight/2;
|
GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size);
|
||||||
GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->targetwidth*videoscale->targetheight*2);
|
|
||||||
GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
|
GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
|
||||||
|
|
||||||
/*g_return_if_fail(videoscale->scale_cc != NULL); */
|
g_return_if_fail(videoscale->format);
|
||||||
videoscale->scale_cc(videoscale, data, GST_BUFFER_DATA(outbuf));
|
GST_DEBUG (0,"format %s",videoscale->format->fourcc);
|
||||||
|
g_return_if_fail(videoscale->format->scale);
|
||||||
|
|
||||||
|
videoscale->format->scale(videoscale, GST_BUFFER_DATA(outbuf), data);
|
||||||
|
|
||||||
GST_DEBUG (0,"gst_videoscale_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf),
|
GST_DEBUG (0,"gst_videoscale_chain: pushing buffer of %d bytes in '%s'",GST_BUFFER_SIZE(outbuf),
|
||||||
GST_OBJECT_NAME (videoscale));
|
GST_OBJECT_NAME (videoscale));
|
||||||
|
@ -288,7 +395,6 @@ GST_DEBUG(0,"size=%ld from=%dx%d to=%dx%d newsize=%d",
|
||||||
|
|
||||||
gst_buffer_unref(buf);
|
gst_buffer_unref(buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_videoscale_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
gst_videoscale_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
@ -302,10 +408,12 @@ gst_videoscale_set_property (GObject *object, guint prop_id, const GValue *value
|
||||||
GST_DEBUG(0,"gst_videoscale_set_property");
|
GST_DEBUG(0,"gst_videoscale_set_property");
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case ARG_WIDTH:
|
case ARG_WIDTH:
|
||||||
src->targetwidth = g_value_get_int (value);
|
src->forced_width = g_value_get_int (value);
|
||||||
|
src->force_size = TRUE;
|
||||||
break;
|
break;
|
||||||
case ARG_HEIGHT:
|
case ARG_HEIGHT:
|
||||||
src->targetheight = g_value_get_int (value);
|
src->forced_height = g_value_get_int (value);
|
||||||
|
src->force_size = TRUE;
|
||||||
break;
|
break;
|
||||||
case ARG_METHOD:
|
case ARG_METHOD:
|
||||||
src->method = g_value_get_enum (value);
|
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) {
|
switch (prop_id) {
|
||||||
case ARG_WIDTH:
|
case ARG_WIDTH:
|
||||||
g_value_set_int (value, src->targetwidth);
|
g_value_set_int (value, src->forced_width);
|
||||||
break;
|
break;
|
||||||
case ARG_HEIGHT:
|
case ARG_HEIGHT:
|
||||||
g_value_set_int (value, src->targetheight);
|
g_value_set_int (value, src->forced_height);
|
||||||
break;
|
break;
|
||||||
case ARG_METHOD:
|
case ARG_METHOD:
|
||||||
g_value_set_enum (value, src->method);
|
g_value_set_enum (value, src->method);
|
||||||
|
@ -351,8 +459,8 @@ plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
&videoscale_details);
|
&videoscale_details);
|
||||||
g_return_val_if_fail(factory != NULL, FALSE);
|
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 (gst_videoscale_sink_template_factory));
|
||||||
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_src_template_factory));
|
||||||
|
|
||||||
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||||
|
|
||||||
|
|
|
@ -57,21 +57,29 @@ struct _GstVideoscale {
|
||||||
|
|
||||||
GstPad *sinkpad,*srcpad;
|
GstPad *sinkpad,*srcpad;
|
||||||
|
|
||||||
|
gboolean force_size;
|
||||||
|
gint forced_width;
|
||||||
|
gint forced_height;
|
||||||
|
|
||||||
/* video state */
|
/* video state */
|
||||||
guint32 format;
|
gboolean inited;
|
||||||
gint width;
|
struct videoscale_format_struct *format;
|
||||||
gint height;
|
gint to_width;
|
||||||
gint targetwidth;
|
gint to_height;
|
||||||
gint targetheight;
|
gint from_width;
|
||||||
|
gint from_height;
|
||||||
|
gboolean passthru;
|
||||||
|
|
||||||
GstVideoScaleMethod method;
|
GstVideoScaleMethod method;
|
||||||
guint scale_bytes;
|
|
||||||
|
|
||||||
/* private */
|
/* private */
|
||||||
|
gint from_buf_size;
|
||||||
|
gint to_buf_size;
|
||||||
|
#if 0
|
||||||
guchar *temp;
|
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 (*filter) (guchar *src, gdouble x, gdouble y, gint sw, gint sh);
|
||||||
guchar copy_row[8192];
|
guchar copy_row[8192];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVideoscaleClass {
|
struct _GstVideoscaleClass {
|
||||||
|
|
|
@ -18,8 +18,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG_ENABLED
|
#define DEBUG_ENABLED
|
||||||
|
#include <gst/gst.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <videoscale.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gstvideoscale.h"
|
#include "gstvideoscale.h"
|
||||||
|
@ -28,79 +31,152 @@
|
||||||
#include "videoscale_x86.h"
|
#include "videoscale_x86.h"
|
||||||
#endif
|
#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 */
|
/* 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);
|
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,
|
static void gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
||||||
int sw, int sh, int dw, int dh);
|
int sw, int sh, int dw, int dh);
|
||||||
static void gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
static void gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
||||||
int sw, int sh, int dw, int dh);
|
int sw, int sh, int dw, int dh);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* filters */
|
/* filters */
|
||||||
static unsigned char gst_videoscale_bilinear (unsigned char *src, double x, double y, int sw, int sh);
|
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 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
|
void
|
||||||
gst_videoscale_setup (GstVideoscale *scale)
|
gst_videoscale_setup (GstVideoscale *videoscale)
|
||||||
{
|
{
|
||||||
switch (scale->format) {
|
GST_DEBUG (0,"format=%p \"%s\" from %dx%d to %dx%d",
|
||||||
case GST_MAKE_FOURCC('I','4','2','0'):
|
videoscale->format, videoscale->format->fourcc,
|
||||||
scale->scale_cc = gst_videoscale_scale_yuv;
|
videoscale->from_width, videoscale->from_height,
|
||||||
scale->scale_bytes = 1;
|
videoscale->to_width, videoscale->to_height);
|
||||||
break;
|
|
||||||
case GST_MAKE_FOURCC('R','G','B',' '):
|
if(videoscale->to_width==0 || videoscale->to_height==0 ||
|
||||||
scale->scale_cc = gst_videoscale_scale_rgb;
|
videoscale->from_width==0 || videoscale->from_height==0){
|
||||||
/* XXX */
|
return;
|
||||||
/*scale->scale_bytes = gst_caps_get_int(scale->srcpad->caps,"bpp")/8; */
|
}
|
||||||
break;
|
|
||||||
default:
|
if(videoscale->to_width == videoscale->from_width &&
|
||||||
g_print("videoscale: unsupported video format %08x\n", scale->format);
|
videoscale->to_height == videoscale->from_height){
|
||||||
return; /* XXX */
|
GST_DEBUG (0,"videoscale: using passthru");
|
||||||
|
videoscale->passthru = TRUE;
|
||||||
|
videoscale->inited = TRUE;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (scale->method) {
|
|
||||||
case GST_VIDEOSCALE_POINT_SAMPLE:
|
|
||||||
scale->scaler = gst_videoscale_scale_point_sample;
|
|
||||||
GST_DEBUG (0,"videoscale: scaling method POINT_SAMPLE");
|
GST_DEBUG (0,"videoscale: scaling method POINT_SAMPLE");
|
||||||
break;
|
|
||||||
case GST_VIDEOSCALE_NEAREST:
|
videoscale->from_buf_size = (videoscale->from_width * videoscale->from_height
|
||||||
#ifdef HAVE_CPU_I386
|
* videoscale->format->depth) / 8;
|
||||||
gst_videoscale_generate_rowbytes_x86 (scale->copy_row, scale->width,
|
videoscale->to_buf_size = (videoscale->to_width * videoscale->to_height
|
||||||
scale->targetwidth, scale->scale_bytes);
|
* videoscale->format->depth) / 8;
|
||||||
scale->scaler = gst_videoscale_scale_nearest_x86;
|
|
||||||
#else
|
videoscale->inited = TRUE;
|
||||||
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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
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 sw = scale->from_width;
|
||||||
int sh = scale->height;
|
int sh = scale->from_height;
|
||||||
int dw = scale->targetwidth;
|
int dw = scale->to_width;
|
||||||
int dh = scale->targetheight;
|
int dh = scale->to_height;
|
||||||
GST_DEBUG (0,"videoscale: scaling RGB %dx%d to %dx%d", sw, sh, dw, dh);
|
GST_DEBUG (0,"videoscale: scaling RGB %dx%d to %dx%d", sw, sh, dw, dh);
|
||||||
|
|
||||||
switch (scale->scale_bytes) {
|
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);
|
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
|
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 sw = scale->from_width;
|
||||||
int sh = scale->height;
|
int sh = scale->from_height;
|
||||||
int dw = scale->targetwidth;
|
int dw = scale->to_width;
|
||||||
int dh = scale->targetheight;
|
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;
|
src += sw*sh;
|
||||||
dest += dw*dh;
|
dest += dw*dh;
|
||||||
|
@ -140,12 +217,85 @@ gst_videoscale_scale_yuv (GstVideoscale *scale, unsigned char *src, unsigned cha
|
||||||
sh = sh>>1;
|
sh = sh>>1;
|
||||||
sw = sw>>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;
|
src += sw*sh;
|
||||||
dest += dw*dh;
|
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))
|
#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;
|
return (unsigned char) color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
gst_videoscale_scale_plane_slow (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
||||||
int sw, int sh, int dw, int dh)
|
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
|
static void
|
||||||
gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
gst_videoscale_scale_point_sample (GstVideoscale *scale, unsigned char *src, unsigned char *dest,
|
||||||
int sw, int sh, int dw, int dh)
|
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;
|
ypos += yinc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_videoscale_scale_nearest (GstVideoscale *scale,
|
gst_videoscale_scale_nearest (GstVideoscale *scale,
|
||||||
unsigned char *src,
|
|
||||||
unsigned char *dest,
|
unsigned char *dest,
|
||||||
|
unsigned char *src,
|
||||||
int sw, int sh, int dw, int dh)
|
int sw, int sh, int dw, int dh)
|
||||||
{
|
{
|
||||||
int ypos, yinc, y;
|
int ypos, yinc, y;
|
||||||
int xpos, xinc, x;
|
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;
|
ypos = 0x10000;
|
||||||
|
@ -316,41 +472,8 @@ gst_videoscale_scale_nearest (GstVideoscale *scale,
|
||||||
|
|
||||||
xpos = 0x10000;
|
xpos = 0x10000;
|
||||||
|
|
||||||
switch (scale->scale_bytes) {
|
srcp = src;
|
||||||
case 4:
|
destp = dest;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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-- ) {
|
for ( x=dw; x; x-- ) {
|
||||||
while ( xpos >= 0x10000L ) {
|
while ( xpos >= 0x10000L ) {
|
||||||
|
@ -360,11 +483,191 @@ gst_videoscale_scale_nearest (GstVideoscale *scale,
|
||||||
*destp++ = *srcp;
|
*destp++ = *srcp;
|
||||||
xpos += xinc;
|
xpos += xinc;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
dest += dw;
|
dest += dw;
|
||||||
|
|
||||||
ypos += yinc;
|
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;
|
||||||
|
}
|
||||||
|
*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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
46
gst/videoscale/videoscale.h
Normal file
46
gst/videoscale/videoscale.h
Normal 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
|
||||||
|
|
Loading…
Reference in a new issue