#include <gstcolorspace.h>
-extern GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace srcspace,
- GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace srcspace,
- GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_rgb2yuv_get_converter(GstColorSpace srcspace,
- GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_yuv2yuv_get_converter(GstColorSpace srcspace,
- GstColorSpace destspace);
-
-GstBuffer *gst_colorspace_convert(GstBuffer *src, GstColorSpace dest) {
- switch (dest) {
- default:
- break;
- }
- return src;
-}
+extern GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace *space, GstColorSpaceType srcspace,
+ GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace *space, GstColorSpaceType srcspace,
+ GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_rgb2yuv_get_converter(GstColorSpace *space, GstColorSpaceType srcspace,
+ GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_yuv2yuv_get_converter(GstColorSpace *space, GstColorSpaceType srcspace,
+ GstColorSpaceType destspace);
+
+GstColorSpace *gst_colorspace_new(int width, int height, GstColorSpaceType srcspace, GstColorSpaceType destspace, GdkVisual *destvisual)
+{
+
+ GstColorSpace *new = g_malloc(sizeof(GstColorSpace));
-GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstColorSpace destspace) {
- DEBUG("gst_colorspace: get converter\n");
+ new->width = width;
+ new->height = height;
+ new->srcspace = srcspace;
+ new->destspace = destspace;
+ new->visual = destvisual;
+ new->convert = NULL;
+
+ DEBUG("gst_colorspace: new\n");
if (GST_COLORSPACE_IS_RGB_TYPE(srcspace)) {
if (GST_COLORSPACE_IS_RGB_TYPE(destspace)) {
- return gst_colorspace_rgb2rgb_get_converter(srcspace, destspace);
+ new->convert = gst_colorspace_rgb2rgb_get_converter(new, srcspace, destspace);
}
else {
//return gst_colorspace_rgb2yuv_get_converter(srcspace, destspace);
}
else if (GST_COLORSPACE_IS_YUV_TYPE(srcspace)) {
if (GST_COLORSPACE_IS_RGB_TYPE(destspace)) {
- return gst_colorspace_yuv2rgb_get_converter(srcspace, destspace);
+ new->convert = gst_colorspace_yuv2rgb_get_converter(new, srcspace, destspace);
}
else {
//return gst_colorspace_yuv2yuv_get_converter(srcspace, destspace);
}
}
- g_print("gst_colorspace: conversion not implemented\n");
- return NULL;
+ if (new->convert == NULL) {
+ g_print("gst_colorspace: conversion not implemented\n");
+ }
+ return new;
+}
+
+void gst_colorspace_destroy(GstColorSpace *space)
+{
+ if (space->color_tables) g_free(space->color_tables);
+ g_free(space);
}
#include <gst/gstbuffer.h>
#include <gst/gstplugin.h>
-typedef enum {
+#include "yuv2rgb.h"
+typedef enum {
#define GST_COLORSPACE_RGB_FIRST GST_COLORSPACE_RGB555
GST_COLORSPACE_RGB555,
GST_COLORSPACE_BGR555,
GST_COLORSPACE_YUV422P,
#define GST_COLORSPACE_YUV_LAST GST_COLORSPACE_YUV422P
-} GstColorSpace;
+} GstColorSpaceType;
-typedef struct _GstColorSpaceParameters GstColorSpaceParameters;
+typedef struct _GstColorSpace GstColorSpace;
+typedef void (*GstColorSpaceConverter) (GstColorSpace *space, unsigned char *src, unsigned char *dest);
-struct _GstColorSpaceParameters {
+struct _GstColorSpace {
guint width;
guint height;
- gchar *outbuf;
+ GstColorSpaceType srcspace;
+ GstColorSpaceType destspace;
GdkVisual *visual;
+ guint insize;
+ guint outsize;
+ /* private */
+ GstColorSpaceYUVTables *color_tables;
+ GstColorSpaceConverter convert;
};
#define GST_COLORSPACE_IS_YUV_TYPE(type) ((type)>=GST_COLORSPACE_YUV_FIRST && \
(type)<=GST_COLORSPACE_YUV_LAST)
-typedef GstBuffer * (*GstColorSpaceConverter) (GstBuffer *src, GstColorSpaceParameters *params);
-
-GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstColorSpace destspace);
-
-/* convert a buffer to a new buffer in the given colorspace */
-GstBuffer *gst_colorspace_convert(GstBuffer *buf, GstColorSpace destspace);
+GstColorSpace *gst_colorspace_new(int width, int height, GstColorSpaceType srcspace, GstColorSpaceType destspace, GdkVisual *destvisual);
+void gst_colorspace_destroy(GstColorSpace *space);
#endif /* __GST_COLORSPACE_H__ */
#include <gst/gst.h>
#include <gstcolorspace.h>
-static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params);
+static void gst_colorspace_rgb_to_rgb_identity(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_rgb24_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
-GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
+GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace *space, GstColorSpaceType src, GstColorSpaceType dest) {
switch(src) {
case GST_COLORSPACE_RGB24:
+ space->insize = space->width*space->height*3;
switch(dest) {
case GST_COLORSPACE_RGB24:
+ space->outsize = space->width*space->height*3;
return gst_colorspace_rgb_to_rgb_identity;
case GST_COLORSPACE_BGR24:
+ space->outsize = space->width*space->height*3;
return gst_colorspace_rgb24_to_bgr24;
default:
break;
}
break;
case GST_COLORSPACE_BGR24:
+ space->insize = space->width*space->height*3;
switch(dest) {
case GST_COLORSPACE_RGB24:
+ space->outsize = space->width*space->height*3;
return gst_colorspace_rgb24_to_bgr24;
case GST_COLORSPACE_BGR24:
+ space->outsize = space->width*space->height*3;
return gst_colorspace_rgb_to_rgb_identity;
default:
break;
return NULL;
}
-static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params) {
- return src;
+static void gst_colorspace_rgb_to_rgb_identity(GstColorSpace *space, unsigned char *src, unsigned char *dest)
+{
+ memcpy(dest, src, space->outsize);
}
-static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_rgb24_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest)
+{
gint size;
gchar temp;
- gchar *data;
- DEBUG("gst_colorspace_rgb24_to_bgr24 %d\n", GST_BUFFER_SIZE(src));
+ DEBUG("gst_colorspace_rgb24_to_bgr24\n");
- size = GST_BUFFER_SIZE(src)/3;
+ size = space->outsize;
- if (params != NULL && params->outbuf != NULL) {
- data = params->outbuf;
- DEBUG("gst_colorspace: to buffer %p\n", data);
+ if (src == dest) {
+ while (size--) {
+ temp = src[0];
+ src[0] = src[2];
+ src[2] = temp;
+ src+=3;
+ }
}
else {
- data = GST_BUFFER_DATA(src);
+ while (size--) {
+ *dest++ = src[2];
+ *dest++ = src[1];
+ *dest++ = src[0];
+ src+=3;
+ }
}
-
- while (size--) {
- temp = data[0];
- data[0] = data[2];
- data[2] = temp;
- data+=3;
- }
- DEBUG("gst_colorspace_rgb24_to_bgr24 end %d\n", GST_BUFFER_SIZE(src));
-
- return src;
+ DEBUG("gst_colorspace_rgb24_to_bgr24 end\n");
}
#include "yuv2rgb.h"
-static GstBuffer *gst_colorspace_yuv420P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params);
+static void gst_colorspace_yuv420P_to_rgb32(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr32(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr32_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_rgb24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_rgb16(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr16_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
unsigned char *lum,
static GstColorSpaceYUVTables * gst_colorspace_init_yuv(long depth,
long red_mask, long green_mask, long blue_mask);
-GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
- DEBUG("gst_colorspace_yuv2rgb_get_converter %d\n", dest);
+GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace *space, GstColorSpaceType src, GstColorSpaceType dest) {
+ DEBUG("gst_colorspace_yuv2rgb_get_converter %d %d\n", src, dest);
switch(src) {
case GST_COLORSPACE_YUV420P:
+ space->insize = space->width*space->height+space->width*space->height/2;
switch(dest) {
case GST_COLORSPACE_BGR32:
+ space->color_tables = gst_colorspace_init_yuv(32, 0xFF0000, 0x00FF00, 0x0000FF);
+ space->outsize = space->width*space->height*4;
//return gst_colorspace_yuv420P_to_bgr32;
return gst_colorspace_yuv420P_to_bgr32_mmx;
case GST_COLORSPACE_RGB32:
+ space->color_tables = gst_colorspace_init_yuv(32, 0x0000FF, 0x00FF00, 0xFF0000);
+ space->outsize = space->width*space->height*4;
return gst_colorspace_yuv420P_to_rgb32;
case GST_COLORSPACE_RGB24:
+ space->color_tables = gst_colorspace_init_yuv(24, 0x0000FF, 0x00FF00, 0xFF0000);
+ space->outsize = space->width*space->height*3;
return gst_colorspace_yuv420P_to_rgb24;
case GST_COLORSPACE_BGR24:
+ space->color_tables = gst_colorspace_init_yuv(24, 0xFF0000, 0x00FF00, 0x0000FF);
+ space->outsize = space->width*space->height*3;
return gst_colorspace_yuv420P_to_bgr24;
case GST_COLORSPACE_RGB555:
case GST_COLORSPACE_RGB565:
case GST_COLORSPACE_BGR555:
+ g_return_val_if_fail(space->visual != NULL, NULL);
+ space->color_tables = gst_colorspace_init_yuv(16, space->visual->red_mask, space->visual->green_mask, space->visual->blue_mask);
+ space->outsize = space->width*space->height*2;
return gst_colorspace_yuv420P_to_rgb16;
case GST_COLORSPACE_BGR565:
+ space->outsize = space->width*space->height*2;
return gst_colorspace_yuv420P_to_bgr16_mmx;
default:
break;
return NULL;
}
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params) {
- static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_bgr32(GstColorSpace *space, unsigned char *src, unsigned char *dest)
+{
int size;
- GstBuffer *buf = NULL;
- guchar *out;
DEBUG("gst_colorspace_yuv420P_to_bgr32\n");
- g_return_val_if_fail(params != NULL, NULL);
+ size = space->width * space->height;
+
+ gst_colorspace_yuv_to_rgb32(space->color_tables,
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
- if (color_tables == NULL) {
- color_tables = gst_colorspace_init_yuv(32, 0xFF0000, 0x00FF00, 0x0000FF);
- }
- size = params->width * params->height;
- if (params->outbuf == NULL) {
- buf = gst_buffer_new();
- out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
- GST_BUFFER_SIZE(buf) = size * 4;
- }
- else out = params->outbuf;
-
- gst_colorspace_yuv_to_rgb32(color_tables,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- out,
- params->height,
- params->width);
-
- if (buf) {
- gst_buffer_unref(src);
- return buf;
- }
- else return src;
}
-static GstBuffer *gst_colorspace_yuv420P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params) {
- static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb32(GstColorSpace *space, unsigned char *src, unsigned char *dest)
+{
int size;
- GstBuffer *buf = NULL;
- guchar *out;
DEBUG("gst_colorspace_yuv420P_to_rgb32\n");
- g_return_val_if_fail(params != NULL, NULL);
- if (color_tables == NULL) {
- color_tables = gst_colorspace_init_yuv(32, 0x0000FF, 0x00FF00, 0xFF0000);
- }
- size = params->width * params->height;
- if (params->outbuf == NULL) {
- buf = gst_buffer_new();
- out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
- GST_BUFFER_SIZE(buf) = size * 4;
- }
- else out = params->outbuf;
-
- gst_colorspace_yuv_to_rgb32(color_tables,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- out,
- params->height,
- params->width);
-
- if (buf) {
- gst_buffer_unref(src);
- return buf;
- }
- else return src;
+ size = space->width * space->height;
+
+ gst_colorspace_yuv_to_rgb32(space->color_tables,
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
+
}
-static GstBuffer *gst_colorspace_yuv420P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
- static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
int size;
- GstBuffer *buf = NULL;
- guchar *out;
DEBUG("gst_colorspace_yuv420P_to_bgr24\n");
- g_return_val_if_fail(params != NULL, NULL);
+ size = space->width * space->height;
- if (color_tables == NULL) {
- color_tables = gst_colorspace_init_yuv(24, 0xFF0000, 0x00FF00, 0x0000FF);
- }
- size = params->width * params->height;
- if (params->outbuf == NULL) {
- buf = gst_buffer_new();
- out = GST_BUFFER_DATA(buf) = g_malloc(size * 3);
- GST_BUFFER_SIZE(buf) = size * 3;
- }
- else out = params->outbuf;
-
- gst_colorspace_yuv_to_rgb24(color_tables,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- out,
- params->height,
- params->width);
- if (buf) {
- gst_buffer_unref(src);
- return buf;
- }
- else return src;
+ gst_colorspace_yuv_to_rgb24(space->color_tables,
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
}
-static GstBuffer *gst_colorspace_yuv420P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params) {
- static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb24(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
int size;
- GstBuffer *buf = NULL;
- guchar *out;
DEBUG("gst_colorspace_yuv420P_to_rgb24\n");
- g_return_val_if_fail(params != NULL, NULL);
+ size = space->width * space->height;
+
+ gst_colorspace_yuv_to_rgb24(space->color_tables,
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
- if (color_tables == NULL) {
- color_tables = gst_colorspace_init_yuv(24, 0x0000FF, 0x00FF00, 0xFF0000);
- }
- size = params->width * params->height;
- if (params->outbuf == NULL) {
- buf = gst_buffer_new();
- out = GST_BUFFER_DATA(buf) = g_malloc(size * 3);
- GST_BUFFER_SIZE(buf) = size * 3;
- }
- else out = params->outbuf;
-
- gst_colorspace_yuv_to_rgb24(color_tables,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- out,
- params->height,
- params->width);
-
- if (buf) {
- gst_buffer_unref(src);
- return buf;
- }
- else return src;
}
-static GstBuffer *gst_colorspace_yuv420P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params) {
- static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb16(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
int size;
DEBUG("gst_colorspace_yuv420P_to_rgb16\n");
- g_return_val_if_fail(params != NULL, NULL);
- g_return_val_if_fail(params->visual != NULL, NULL);
-
- if (color_tables == NULL) {
- color_tables = gst_colorspace_init_yuv(16, params->visual->red_mask, params->visual->green_mask, params->visual->blue_mask);
- }
- size = params->width * params->height;
+ size = space->width * space->height;
- gst_colorspace_yuv_to_rgb16(color_tables,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- params->outbuf,
- params->height,
- params->width);
+ gst_colorspace_yuv_to_rgb16(space->color_tables,
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
- return src;
}
#ifdef HAVE_LIBMMX
static mmx_t MMX16_redmask = (mmx_t)(long long)0xf800f800f800f800LL; //dd 07c00 7c00h, 07c007c00h
static mmx_t MMX16_grnmask = (mmx_t)(long long)0x07e007e007e007e0LL; //dd 003e0 03e0h, 003e003e0h
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_yuv420P_to_bgr32_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
int size;
- GstBuffer *buf = NULL;
- guchar *out;
DEBUG("gst_colorspace_yuv420P_to_rgb32_mmx\n");
- g_return_val_if_fail(params != NULL, NULL);
-
- size = params->width * params->height;
- if (params->outbuf == NULL) {
- buf = gst_buffer_new();
- out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
- GST_BUFFER_SIZE(buf) = size * 4;
- }
- else out = params->outbuf;
+ size = space->width * space->height;
gst_colorspace_yuv_to_bgr32_mmx(NULL,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- out,
- params->height,
- params->width);
-
- if (buf) {
- gst_buffer_unref(src);
- return buf;
- }
- else return src;
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
+
}
-static GstBuffer *gst_colorspace_yuv420P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_yuv420P_to_bgr16_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
int size;
DEBUG("gst_colorspace_yuv420P_to_bgr16_mmx \n");
- g_return_val_if_fail(params != NULL, NULL);
-
- size = params->width * params->height;
+ size = space->width * space->height;
gst_colorspace_yuv_to_bgr16_mmx(NULL,
- GST_BUFFER_DATA(src), // Y component
- GST_BUFFER_DATA(src)+size, // cr component
- GST_BUFFER_DATA(src)+size+(size>>2), // cb component
- params->outbuf,
- params->height,
- params->width);
+ src, // Y component
+ src+size, // cr component
+ src+size+(size>>2), // cb component
+ dest,
+ space->height,
+ space->width);
DEBUG("gst_colorspace_yuv420P_to_bgr16_mmx done\n");
- return src;
}
#endif
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
+#ifndef __YUV2RGB_H__
+#define __YUV2RGB_H__
+
typedef struct _GstColorSpaceYUVTables GstColorSpaceYUVTables;
struct _GstColorSpaceYUVTables {
? Min(127.0, ((x) * chromaCorrect)) \
: Max(-128.0, ((x) * chromaCorrect)))
+#endif
noinst_HEADERS = yuv2rgb.h
-CFLAGS += -Wall -O2 -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
+CFLAGS += -Wall -O2 -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include
LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_srcdir)/gst/libgst.la
#include <gstvideoscale.h>
#include <gst/meta/videoraw.h>
-static void gst_videoscale_scale_plane(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
-static void gst_videoscale_scale_plane_slow(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
-
-GstBuffer *gst_videoscale_scale(GstBuffer *src, int sw, int sh, int dw, int dh, int format) {
- GstBuffer *outbuf;
- char *source;
- char *dest;
- GstMeta *meta;
-
- DEBUG("videoscale: scaling %dx%d to %dx%d\n", sw, sh, dw, dh);
-
- source = GST_BUFFER_DATA(src);
+static void gst_videoscale_scale_yuv(GstVideoScale *scale, unsigned char *src, unsigned char *dest);
+
+/* scalers */
+static void generate_rowbytes(unsigned char *copy_row, int src_w, int dst_w, int bpp);
+static void gst_videoscale_scale_nearest(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
+static void gst_videoscale_scale_plane_slow(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
+
+/* 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);
+
+GstVideoScale *gst_videoscale_new(int sw, int sh, int dw, int dh, int format, GstVideoScaleMethod method)
+{
+ GstVideoScale *new = g_malloc(sizeof(GstVideoScale));
+
+ new->source_width = sw;
+ new->source_height = sh;
+ new->dest_width = dw;
+ new->dest_height = dh;
+ new->format = format;
+ new->method = method;
+
+
+ new->scale = gst_videoscale_scale_yuv;
+
+ switch (method) {
+ case GST_VIDEOSCALE_NEAREST:
+ generate_rowbytes(new->copy_row, sw, dw, 1);
+ new->scaler = gst_videoscale_scale_nearest;
+ DEBUG("videoscale: scaling method NEAREST\n");
+ break;
+ case GST_VIDEOSCALE_BILINEAR:
+ new->scaler = gst_videoscale_scale_plane_slow;
+ new->filter = gst_videoscale_bilinear;
+ break;
+ case GST_VIDEOSCALE_BICUBIC:
+ new->scaler = gst_videoscale_scale_plane_slow;
+ new->filter = gst_videoscale_bicubic;
+ break;
+ default:
+ g_print("videoscale: unsupported scaling method %d\n", method);
+ break;
+ }
- outbuf = gst_buffer_new();
- dest = GST_BUFFER_DATA(outbuf) = g_malloc((dw*dh*12)/8);
- GST_BUFFER_SIZE(outbuf) = (dw*dh*12)/8;
+ return new;
+}
- meta = gst_buffer_get_first_meta(src);
- if (meta) {
- ((MetaVideoRaw *)meta)->width = dw;
- ((MetaVideoRaw *)meta)->height = dh;
+void gst_videoscale_destroy(GstVideoScale *scale)
+{
+ g_free(scale);
+}
- gst_buffer_add_meta(outbuf, meta);
- }
+static void gst_videoscale_scale_yuv(GstVideoScale *scale, unsigned char *src, unsigned char *dest)
+{
+ int sw = scale->source_width;
+ int sh = scale->source_height;
+ int dw = scale->dest_width;
+ int dh = scale->dest_height;
+
+ DEBUG("videoscale: scaling YUV420 %dx%d to %dx%d\n", sw, sh, dw, dh);
- gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
+ scale->scaler(scale, src, dest, sw, sh, dw, dh);
- source += sw*sh;
+ src += sw*sh;
dest += dw*dh;
dh = dh>>1;
sh = sh>>1;
sw = sw>>1;
- gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
+ scale->scaler(scale, src, dest, sw, sh, dw, dh);
- source += sw*sh;
+ src += sw*sh;
dest += dw*dh;
- gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
-
- gst_buffer_unref(src);
-
- return outbuf;
+ scale->scaler(scale, src, dest, sw, sh, dw, dh);
}
#define RC(x,y) *(src+(int)(x)+(int)((y)*sw))
-static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, double y, int sw) {
+static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, double y, int sw, int sh) {
int j=floor(x);
int k=floor(y);
double a=x-j;
int color;
dest=(1-a)*(1-b)*RC(j,k)+
- a*(1-b)*RC(j+1,k)+
- b*(1-a)*RC(j,k+1)+
+ a*(1-b)*RC(j+1,k);
+
+ k = MIN(sh-1, k);
+ dest+= b*(1-a)*RC(j,k+1)+
a*b*RC(j+1,k+1);
color=rint(dest);
return (unsigned char) color;
}
-static void gst_videoscale_scale_plane_slow(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh) {
+static void gst_videoscale_scale_plane_slow(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh)
+{
double zoomx = ((double)dw)/(double)sw;
double zoomy = ((double)dh)/(double)sh;
double xr, yr;
*dest++ = RC(xr, yr);
}
else {
- //*dest++ = gst_videoscale_bilinear(src, xr, yr, sw);
- *dest++ = gst_videoscale_bicubic(src, xr, yr, sw, sh);
+ *dest++ = scale->filter(src, xr, yr, sw, sh);
+ //*dest++ = gst_videoscale_bicubic(src, xr, yr, sw, sh);
}
}
}
}
-static void gst_videoscale_scale_plane(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh) {
-
- int yinc = sh / dh;
- int srcys = sh % dh;
- int destys = dh;
- int dy = 2 * (srcys - destys);
- int incyE = 2 * srcys;
- int incyNE = 2 * (srcys - destys);
- int x, y;
-
- int xinc = sw / dw;
- int srcxs = sw % dw;
- int destxs = dw;
- int incxE = 2 * srcxs;
- int incxNE = 2 * (srcxs - destxs);
- int dx;
- unsigned char *sourcep;
- int srcinc = 0;
- int xskip, yskip =0;
-
- for (y = 0; y<dh; y++) {
-
- dx = 2 * (srcxs - destxs);
- sourcep = src + (srcinc*sw);
-
- for (x = dw; x; x--) {
- if (dx <= 0) {
- dx += incxE;
- xskip = 0;
- }
- else {
- dx += incxNE;
- xskip = 1;
- sourcep++;
+#define PREFIX16 0x66
+#define STORE_BYTE 0xAA
+#define STORE_WORD 0xAB
+#define LOAD_BYTE 0xAC
+#define LOAD_WORD 0xAD
+#define RETURN 0xC3
+
+static void generate_rowbytes(unsigned char *copy_row, int src_w, int dst_w, int bpp)
+{
+ int i;
+ int pos, inc;
+ unsigned char *eip;
+ unsigned char load, store;
+
+ DEBUG("videoscale: setup scaling %p\n", copy_row);
+
+ switch (bpp) {
+ case 1:
+ load = LOAD_BYTE;
+ store = STORE_BYTE;
+ break;
+ case 2:
+ case 4:
+ load = LOAD_WORD;
+ store = STORE_WORD;
+ break;
+ default:
+ return;
+ }
+ pos = 0x10000;
+ inc = (src_w << 16) / dst_w;
+ eip = copy_row;
+ for ( i=0; i<dst_w; ++i ) {
+ while ( pos >= 0x10000L ) {
+ if ( bpp == 2 ) {
+ *eip++ = PREFIX16;
}
- sourcep += xinc;
-
- *dest++ = *sourcep;
+ *eip++ = load;
+ pos -= 0x10000L;
}
- if (dy <= 0) {
- dy += incyE;
- yskip = 0;
+ if ( bpp == 2 ) {
+ *eip++ = PREFIX16;
}
- else {
- dy += incyNE;
- srcinc++;
- yskip = 1;
+ *eip++ = store;
+ pos += inc;
+ }
+ *eip++ = RETURN;
+}
+
+
+static void gst_videoscale_scale_nearest(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh)
+{
+ int pos, inc, y;
+ int u1, u2;
+
+ scale->temp = scale->copy_row;
+
+ DEBUG("videoscale: scaling nearest %p\n", scale->copy_row);
+
+ pos = 0x10000;
+ inc = (sh<<16)/dh;
+
+ for (y = dh; y; y--) {
+
+ while (pos >0x10000) {
+ src += sw;
+ pos-=0x10000;
}
- srcinc += yinc;
+ __asm__ __volatile__ ("
+ movl %2, %%eax\n
+ call *%%eax
+ "
+ : "=&D" (u1), "=&S" (u2)
+ : "g" (scale->temp), "0" (dest), "1" (src)
+ : "memory" );
+
+ dest+= dw;
+
+ pos += inc;
}
+ DEBUG("videoscale: scaling nearest done %p\n", scale->copy_row);
}
#ifndef __GST_VIDEOSCALE_H__
#define __GST_VIDEOSCALE_H__
-#include <gdk/gdk.h>
-#include <gst/gstbuffer.h>
-#include <gst/gstplugin.h>
+#include <gst/gst.h>
-GstBuffer *gst_videoscale_scale(GstBuffer *src, int sw, int sh, int dw, int dh, int format);
+typedef enum {
+ GST_VIDEOSCALE_NEAREST,
+ GST_VIDEOSCALE_BILINEAR,
+ GST_VIDEOSCALE_BICUBIC
+} GstVideoScaleMethod;
+
+typedef struct _GstVideoScale GstVideoScale;
+
+struct _GstVideoScale {
+ guint source_width;
+ guint source_height;
+ guint dest_width;
+ guint dest_height;
+ guint format;
+ GstVideoScaleMethod method;
+ /* private */
+ guchar copy_row[4096];
+ guchar *temp;
+ void (*scale) (GstVideoScale *scale, unsigned char *src, unsigned char *dest);
+ void (*scaler) (GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
+ unsigned char (*filter) (unsigned char *src, double x, double y, int sw, int sh);
+};
+
+GstVideoScale *gst_videoscale_new(int sw, int sh, int dw, int dh, int format, GstVideoScaleMethod method);
+void gst_videoscale_destroy(GstVideoScale *scale);
#endif /* __GST_VIDEOSCALE_H__ */
}
void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
- GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *show;
+ GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *videoscale, *show;
GstElement *audio_queue, *video_queue;
GstElement *audio_thread, *video_thread;
gst_plugin_load("mp1videoparse");
gst_plugin_load(VIDEO_DECODER);
+ gst_plugin_load("videoscale");
gst_plugin_load("videosink");
// construct internal pipeline elements
parse_video = gst_elementfactory_make("mp1videoparse","parse_video");
g_return_if_fail(parse_video != NULL);
decode_video = gst_elementfactory_make(VIDEO_DECODER,"decode_video");
g_return_if_fail(decode_video != NULL);
+ videoscale = gst_elementfactory_make("videoscale","videoscale");
+ g_return_if_fail(videoscale != NULL);
+ gtk_object_set(GTK_OBJECT(videoscale),"width",704, "height", 576,NULL);
+
+
show = gst_elementfactory_make("videosink","show");
g_return_if_fail(show != NULL);
//gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
g_return_if_fail(video_thread != NULL);
gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(parse_video));
gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(decode_video));
+ gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(videoscale));
gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(show));
// set up pad connections
gst_pad_connect(gst_element_get_pad(parse_video,"src"),
gst_element_get_pad(decode_video,"sink"));
gst_pad_connect(gst_element_get_pad(decode_video,"src"),
+ // gst_element_get_pad(videoscale,"sink"));
+ //gst_pad_connect(gst_element_get_pad(videoscale,"src"),
gst_element_get_pad(show,"sink"));
// construct queue and connect everything in the main pipeline
g_return_if_fail(decode_video != NULL);
videoscale = gst_elementfactory_make("videoscale","videoscale");
g_return_if_fail(videoscale != NULL);
- g_return_if_fail(median != NULL);
+ gtk_object_set(GTK_OBJECT(videoscale),"width",352, "height", 240,NULL);
median = gst_elementfactory_make("median","median");
- gtk_object_set(GTK_OBJECT(median),"filtersize",5,NULL);
+ g_return_if_fail(median != NULL);
+ gtk_object_set(GTK_OBJECT(median),"filtersize",9,NULL);
smooth = gst_elementfactory_make("smooth","smooth");
g_return_if_fail(smooth != NULL);
gtk_object_set(GTK_OBJECT(smooth),"filtersize",5,NULL);
gtk_object_set(GTK_OBJECT(smooth),"tolerance",9,NULL);
-
- gtk_object_set(GTK_OBJECT(videoscale),"width",352, "height", 240,NULL);
encode = gst_elementfactory_make("mpeg2enc","encode");
- gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL);
g_return_if_fail(encode != NULL);
+ gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL);
//encode = gst_elementfactory_make("mpeg1encoder","encode");
//gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
gst_pad_connect(gst_element_get_pad(parse_video,"src"),
gst_element_get_pad(decode_video,"sink"));
gst_pad_connect(gst_element_get_pad(decode_video,"src"),
- gst_element_get_pad(videoscale,"sink"));
- gst_pad_connect(gst_element_get_pad(videoscale,"src"),
gst_element_get_pad(median,"sink"));
gst_pad_connect(gst_element_get_pad(median,"src"),
+ gst_element_get_pad(videoscale,"sink"));
+ gst_pad_connect(gst_element_get_pad(videoscale,"src"),
// gst_element_get_pad(smooth,"sink"));
//gst_pad_connect(gst_element_get_pad(smooth,"src"),
gst_element_get_pad(encode,"sink"));