Duplicate the ext/hermes colorspace plugin, and remove Hermes code and GPL code. Fix for new caps negotiation. Rewr...

Original commit message from CVS:
* configure.ac:
* gst/colorspace/Makefile.am:
* gst/colorspace/gstcolorspace.c:
* gst/colorspace/gstcolorspace.h:
* gst/colorspace/yuv2rgb.c:
* gst/colorspace/yuv2rgb.h:
Duplicate the ext/hermes colorspace plugin, and remove Hermes
code and GPL code.  Fix for new caps negotiation.  Rewrite
much of the format handling code, and some of the conversion
code.  Basically, rewrote almost everything.  This element
handles I420, YV12 to RGB conversions.
* ext/hermes/Makefile.am:
* ext/hermes/gsthermescolorspace.c:
Rename colorspace to hermescolorspace.  Fix negotiation issues.
Remove non-Hermes related code.  This element handles lots of
RGB to RGB conversions, but no YUV.
* ext/hermes/gstcolorspace.c:
* ext/hermes/gstcolorspace.h:
* ext/hermes/rgb2yuv.c:
* ext/hermes/yuv2rgb.c:
* ext/hermes/yuv2rgb.h:
* ext/hermes/yuv2rgb_mmx16.s:
* ext/hermes/yuv2yuv.c:
* ext/hermes/yuv2yuv.h:
Remove old code.
This commit is contained in:
David Schleef 2004-01-15 08:58:22 +00:00
parent 4506b4c38b
commit 4910efb9b7
13 changed files with 1226 additions and 992 deletions

View file

@ -1,3 +1,31 @@
2004-01-15 David Schleef <ds@schleef.org>
* configure.ac:
* gst/colorspace/Makefile.am:
* gst/colorspace/gstcolorspace.c:
* gst/colorspace/gstcolorspace.h:
* gst/colorspace/yuv2rgb.c:
* gst/colorspace/yuv2rgb.h:
Duplicate the ext/hermes colorspace plugin, and remove Hermes
code and GPL code. Fix for new caps negotiation. Rewrite
much of the format handling code, and some of the conversion
code. Basically, rewrote almost everything. This element
handles I420, YV12 to RGB conversions.
* ext/hermes/Makefile.am:
* ext/hermes/gsthermescolorspace.c:
Rename colorspace to hermescolorspace. Fix negotiation issues.
Remove non-Hermes related code. This element handles lots of
RGB to RGB conversions, but no YUV.
* ext/hermes/gstcolorspace.c:
* ext/hermes/gstcolorspace.h:
* ext/hermes/rgb2yuv.c:
* ext/hermes/yuv2rgb.c:
* ext/hermes/yuv2rgb.h:
* ext/hermes/yuv2rgb_mmx16.s:
* ext/hermes/yuv2yuv.c:
* ext/hermes/yuv2yuv.h:
Remove old code.
2004-01-14 Colin Walters <walters@verbum.org>
* ext/mad/gstid3tag.c (gst_id3_tag_chain): Don't nego caps if

View file

@ -341,6 +341,7 @@ GST_PLUGINS_ALL="\
avi \
cdxaparse \
chart \
colorspace \
cutter \
debug \
deinterlace \
@ -1525,6 +1526,7 @@ gst/avi/Makefile
gst/asfdemux/Makefile
gst/cdxaparse/Makefile
gst/chart/Makefile
gst/colorspace/Makefile
gst/cutter/Makefile
gst/debug/Makefile
gst/deinterlace/Makefile

View file

@ -1,21 +1,10 @@
plugin_LTLIBRARIES = libgstcolorspace.la
plugin_LTLIBRARIES = libgsthermescolorspace.la
if HAVE_CPU_I386
ARCHSRCS = yuv2rgb_mmx16.s
else
ARCHSRCS =
endif
if USE_HERMES
PLUGIN_EXTRA_LIBS = $(HERMES_LIBS)
else
PLUGIN_EXTRA_LIBS =
endif
libgstcolorspace_la_SOURCES = gstcolorspace.c yuv2yuv.c yuv2rgb.c rgb2yuv.c $(ARCHSRCS)
libgstcolorspace_la_CFLAGS = $(GST_CFLAGS)
libgstcolorspace_la_LIBADD = $(PLUGIN_EXTRA_LIBS)
libgstcolorspace_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgsthermescolorspace_la_SOURCES = gsthermescolorspace.c
libgsthermescolorspace_la_CFLAGS = $(GST_CFLAGS)
libgsthermescolorspace_la_LIBADD = $(PLUGIN_EXTRA_LIBS)
libgsthermescolorspace_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstcolorspace.h yuv2rgb.h yuv2yuv.h

View file

@ -0,0 +1,650 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/video/video.h>
#include <Hermes/Hermes.h>
#define GST_TYPE_COLORSPACE \
(gst_hermes_colorspace_get_type())
#define GST_HERMES_COLORSPACE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COLORSPACE,GstHermesColorspace))
#define GST_HERMES_COLORSPACE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstHermesColorspace))
#define GST_IS_COLORSPACE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COLORSPACE))
#define GST_IS_COLORSPACE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COLORSPACE))
typedef struct _GstHermesColorspace GstHermesColorspace;
typedef struct _GstHermesColorspaceClass GstHermesColorspaceClass;
typedef enum {
GST_HERMES_COLORSPACE_NONE,
GST_HERMES_COLORSPACE_HERMES,
GST_HERMES_COLORSPACE_YUV_RGB,
GST_HERMES_COLORSPACE_YUY2_I420,
GST_HERMES_COLORSPACE_RGB32_I420,
GST_HERMES_COLORSPACE_RGB32_YV12,
GST_HERMES_COLORSPACE_420_SWAP,
} GstColorSpaceConverterType;
struct _GstHermesColorspace {
GstElement element;
GstPad *sinkpad,*srcpad;
HermesHandle h_handle;
HermesFormat sink_format;
HermesFormat src_format;
int src_format_index;
int sink_format_index;
int src_size;
int sink_size;
int src_stride;
int sink_stride;
gint width, height;
gdouble fps;
gboolean passthru;
};
struct _GstHermesColorspaceClass {
GstElementClass parent_class;
};
GType gst_hermes_colorspace_get_type(void);
typedef struct _GstHermesColorspaceFormat {
GstStaticCaps caps;
} GstHermesColorspaceFormat;
static GstHermesColorspaceFormat gst_hermes_colorspace_formats[] = {
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32_REVERSE) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_15) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_16) },
};
static GstElementDetails colorspace_details = {
"Colorspace converter",
"Filter/Converter/Video",
"Converts video from one colorspace to another using libhermes",
"Wim Taymans <wim.taymans@chello.be>",
};
/* Stereo signals and args */
enum {
/* FILL ME */
LAST_SIGNAL
};
enum {
ARG_0,
ARG_SOURCE,
ARG_DEST,
};
static void gst_hermes_colorspace_base_init (gpointer g_class);
static void gst_hermes_colorspace_class_init (GstHermesColorspaceClass *klass);
static void gst_hermes_colorspace_init (GstHermesColorspace *space);
static void gst_hermes_colorspace_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
static void gst_hermes_colorspace_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static GstPadLinkReturn
gst_hermes_colorspace_link (GstPad *pad, const GstCaps *caps);
static void gst_hermes_colorspace_chain (GstPad *pad, GstData *_data);
static GstElementStateReturn
gst_hermes_colorspace_change_state (GstElement *element);
static GstElementClass *parent_class = NULL;
/*static guint gst_hermes_colorspace_signals[LAST_SIGNAL] = { 0 }; */
#if 0
static gboolean
colorspace_setup_converter (GstHermesColorspace *space, GstCaps *from_caps, GstCaps *to_caps)
{
guint32 from_space, to_space;
GstStructure *from_struct;
GstStructure *to_struct;
g_return_val_if_fail (to_caps != NULL, FALSE);
g_return_val_if_fail (from_caps != NULL, FALSE);
from_struct = gst_caps_get_structure (from_caps, 0);
to_struct = gst_caps_get_structure (to_caps, 0);
from_space = GST_MAKE_FOURCC ('R','G','B',' ');
gst_structure_get_fourcc (from_struct, "format", &from_space);
to_space = GST_MAKE_FOURCC ('R','G','B',' ');
gst_structure_get_fourcc (to_struct, "format", &to_space);
GST_INFO ("set up converter for " GST_FOURCC_FORMAT
" (%08x) to " GST_FOURCC_FORMAT " (%08x)",
GST_FOURCC_ARGS (from_space), from_space,
GST_FOURCC_ARGS (to_space), to_space);
switch (from_space) {
case GST_MAKE_FOURCC ('R','G','B',' '):
{
gint from_bpp;
gst_structure_get_int (from_struct, "bpp", &from_bpp);
switch (to_space) {
case GST_MAKE_FOURCC ('R','G','B',' '):
#ifdef HAVE_HERMES
{
gint to_bpp;
gst_structure_get_int (to_struct, "bpp", &to_bpp);
gst_structure_get_int (from_struct, "red_mask", &space->source.r);
gst_structure_get_int (from_struct, "green_mask", &space->source.g);
gst_structure_get_int (from_struct, "blue_mask", &space->source.b);
space->source.a = 0;
space->srcbpp = space->source.bits = from_bpp;
space->source.indexed = 0;
space->source.has_colorkey = 0;
GST_INFO ( "source red mask %08x", space->source.r);
GST_INFO ( "source green mask %08x", space->source.g);
GST_INFO ( "source blue mask %08x", space->source.b);
GST_INFO ( "source bpp %08x", space->srcbpp);
gst_structure_get_int (to_struct, "red_mask", &space->dest.r);
gst_structure_get_int (to_struct, "green_mask", &space->dest.g);
gst_structure_get_int (to_struct, "blue_mask", &space->dest.b);
space->dest.a = 0;
space->destbpp = space->dest.bits = to_bpp;
space->dest.indexed = 0;
space->dest.has_colorkey = 0;
GST_INFO ( "dest red mask %08x", space->dest.r);
GST_INFO ( "dest green mask %08x", space->dest.g);
GST_INFO ( "dest blue mask %08x", space->dest.b);
GST_INFO ( "dest bpp %08x", space->destbpp);
if (!Hermes_ConverterRequest (space->h_handle, &space->source, &space->dest)) {
g_warning ("Hermes: could not get converter\n");
return FALSE;
}
GST_INFO ( "converter set up");
space->type = GST_HERMES_COLORSPACE_HERMES;
return TRUE;
}
#else
g_warning ("colorspace: compiled without hermes!");
return FALSE;
#endif
case GST_MAKE_FOURCC ('Y','V','1','2'):
if (from_bpp == 32) {
space->type = GST_HERMES_COLORSPACE_RGB32_YV12;
space->destbpp = 12;
return TRUE;
}
case GST_MAKE_FOURCC ('I','4','2','0'):
if (from_bpp == 32) {
space->type = GST_HERMES_COLORSPACE_RGB32_I420;
space->destbpp = 12;
return TRUE;
}
case GST_MAKE_FOURCC ('Y','U','Y','2'):
GST_INFO ( "colorspace: RGB to YUV with bpp %d not implemented!!", from_bpp);
return FALSE;
}
break;
}
case GST_MAKE_FOURCC ('I','4','2','0'):
switch (to_space) {
case GST_MAKE_FOURCC ('R','G','B',' '):
GST_INFO ( "colorspace: YUV to RGB");
gst_structure_get_int (to_struct, "bpp", &space->destbpp);
space->converter = gst_hermes_colorspace_yuv2rgb_get_converter (from_caps, to_caps);
space->type = GST_HERMES_COLORSPACE_YUV_RGB;
return TRUE;
case GST_MAKE_FOURCC ('I','4','2','0'):
space->type = GST_HERMES_COLORSPACE_NONE;
space->destbpp = 12;
return TRUE;
case GST_MAKE_FOURCC ('Y','V','1','2'):
space->type = GST_HERMES_COLORSPACE_420_SWAP;
space->destbpp = 12;
return TRUE;
}
break;
case GST_MAKE_FOURCC ('Y','U','Y','2'):
switch (to_space) {
case GST_MAKE_FOURCC ('I','4','2','0'):
space->type = GST_HERMES_COLORSPACE_YUY2_I420;
space->destbpp = 12;
return TRUE;
case GST_MAKE_FOURCC ('Y','U','Y','2'):
space->type = GST_HERMES_COLORSPACE_NONE;
space->destbpp = 16;
return TRUE;
case GST_MAKE_FOURCC ('R','G','B',' '):
GST_INFO ( "colorspace: YUY2 to RGB not implemented!!");
return FALSE;
}
break;
case GST_MAKE_FOURCC ('Y','V','1','2'):
switch (to_space) {
case GST_MAKE_FOURCC ('R','G','B',' '):
GST_INFO ( "colorspace: YV12 to RGB");
gst_structure_get_int (to_struct, "bpp", &space->destbpp);
space->converter = gst_hermes_colorspace_yuv2rgb_get_converter (from_caps, to_caps);
space->type = GST_HERMES_COLORSPACE_YUV_RGB;
return TRUE;
case GST_MAKE_FOURCC ('I','4','2','0'):
space->type = GST_HERMES_COLORSPACE_420_SWAP;
space->destbpp = 12;
return TRUE;
case GST_MAKE_FOURCC ('Y','V','1','2'):
space->type = GST_HERMES_COLORSPACE_NONE;
space->destbpp = 12;
return TRUE;
}
break;
}
return FALSE;
}
#endif
static GstCaps *
gst_hermes_colorspace_caps_remove_format_info (GstCaps *caps)
{
int i;
GstStructure *structure;
GstCaps *rgbcaps;
for (i=0; i<gst_caps_get_size (caps); i++) {
structure = gst_caps_get_structure (caps, i);
gst_structure_remove_field (structure, "format");
gst_structure_remove_field (structure, "endianness");
gst_structure_remove_field (structure, "depth");
gst_structure_remove_field (structure, "bpp");
gst_structure_remove_field (structure, "red_mask");
gst_structure_remove_field (structure, "green_mask");
gst_structure_remove_field (structure, "blue_mask");
}
rgbcaps = gst_caps_simplify (caps);
gst_caps_free (caps);
return rgbcaps;
}
static void
gst_hermes_colorspace_structure_to_hermes_format (HermesFormat *format,
GstStructure *structure)
{
gst_structure_get_int (structure, "red_mask", &format->r);
gst_structure_get_int (structure, "green_mask", &format->g);
gst_structure_get_int (structure, "blue_mask", &format->b);
format->a = 0;
gst_structure_get_int (structure, "bpp", &format->bits);
format->indexed = 0;
format->has_colorkey = 0;
}
static GstCaps*
gst_hermes_colorspace_getcaps (GstPad *pad)
{
GstHermesColorspace *space;
GstPad *otherpad;
GstCaps *othercaps;
GstCaps *caps;
space = GST_HERMES_COLORSPACE (gst_pad_get_parent (pad));
otherpad = (pad == space->srcpad) ? space->sinkpad : space->srcpad;
othercaps = gst_pad_get_allowed_caps (otherpad);
othercaps = gst_hermes_colorspace_caps_remove_format_info (othercaps);
caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
gst_caps_free (othercaps);
return caps;
}
static GstPadLinkReturn
gst_hermes_colorspace_link (GstPad *pad, const GstCaps *caps)
{
GstHermesColorspace *space;
GstPad *otherpad;
GstStructure *structure;
GstPadLinkReturn link_ret;
int width, height;
double fps;
int i;
space = GST_HERMES_COLORSPACE (gst_pad_get_parent (pad));
otherpad = (pad == space->sinkpad) ? space->srcpad : space->sinkpad;
link_ret = gst_pad_try_set_caps (otherpad, caps);
if (link_ret == GST_PAD_LINK_OK) {
space->passthru = TRUE;
return link_ret;
}
structure = gst_caps_get_structure (caps, 0);
for(i=0; i<G_N_ELEMENTS (gst_hermes_colorspace_formats); i++) {
GstCaps *icaps;
GstCaps *fcaps;
fcaps = gst_caps_copy (gst_static_caps_get (
&gst_hermes_colorspace_formats[i].caps));
icaps = gst_caps_intersect (caps, fcaps);
if (!gst_caps_is_empty (icaps)) {
break;
}
gst_caps_free (icaps);
}
if (i==G_N_ELEMENTS (gst_hermes_colorspace_formats)) {
g_assert_not_reached ();
return GST_PAD_LINK_REFUSED;
}
gst_structure_get_int (structure, "width", &width);
gst_structure_get_int (structure, "height", &height);
gst_structure_get_double (structure, "framerate", &fps);
GST_INFO ( "size: %dx%d", space->width, space->height);
if (gst_pad_is_negotiated (otherpad)) {
GstCaps *othercaps;
othercaps = gst_caps_copy (gst_pad_get_negotiated_caps (otherpad));
gst_caps_set_simple (othercaps,
"width", G_TYPE_INT, width,
"height", G_TYPE_INT, height,
"framerate", G_TYPE_DOUBLE, fps, NULL);
link_ret = gst_pad_try_set_caps (otherpad, othercaps);
if (link_ret != GST_PAD_LINK_OK) {
return link_ret;
}
}
if (pad == space->srcpad) {
space->src_format_index = i;
gst_hermes_colorspace_structure_to_hermes_format (&space->src_format, structure);
} else {
space->sink_format_index = i;
gst_hermes_colorspace_structure_to_hermes_format (&space->sink_format, structure);
}
space->sink_stride = width*(space->sink_format.bits/8);
space->src_stride = width*(space->src_format.bits/8);
space->sink_size = space->sink_stride * height;
space->src_size = space->src_stride * height;
space->width = width;
space->height = height;
space->fps = fps;
if (gst_pad_is_negotiated (otherpad)) {
if (!Hermes_ConverterRequest (space->h_handle, &space->sink_format,
&space->src_format)) {
g_warning ("Hermes: could not get converter\n");
return GST_PAD_LINK_REFUSED;
}
g_print("inited\n");
}
return GST_PAD_LINK_OK;
}
GType
gst_hermes_colorspace_get_type (void)
{
static GType colorspace_type = 0;
if (!colorspace_type) {
static const GTypeInfo colorspace_info = {
sizeof(GstHermesColorspaceClass),
gst_hermes_colorspace_base_init,
NULL,
(GClassInitFunc)gst_hermes_colorspace_class_init,
NULL,
NULL,
sizeof(GstHermesColorspace),
0,
(GInstanceInitFunc)gst_hermes_colorspace_init,
};
colorspace_type = g_type_register_static(GST_TYPE_ELEMENT, "GstHermesColorspace", &colorspace_info, 0);
}
return colorspace_type;
}
static GstStaticPadTemplate gst_hermes_colorspace_src_pad_template =
GST_STATIC_PAD_TEMPLATE (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
GST_VIDEO_YUV_PAD_TEMPLATE_CAPS ("{ I420, YV12, YUY2 }") "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32_REVERSE "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_15 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_16)
);
static GstStaticPadTemplate gst_hermes_colorspace_sink_pad_template =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
GST_VIDEO_YUV_PAD_TEMPLATE_CAPS ("{ I420, YV12, YUY2 }") "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32_REVERSE "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_15 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_16)
);
static void
gst_hermes_colorspace_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_hermes_colorspace_src_pad_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_hermes_colorspace_sink_pad_template));
gst_element_class_set_details (element_class, &colorspace_details);
}
static void
gst_hermes_colorspace_class_init (GstHermesColorspaceClass *klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass*)klass;
gstelement_class = (GstElementClass*)klass;
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
gobject_class->set_property = gst_hermes_colorspace_set_property;
gobject_class->get_property = gst_hermes_colorspace_get_property;
gstelement_class->change_state = gst_hermes_colorspace_change_state;
}
static void
gst_hermes_colorspace_init (GstHermesColorspace *space)
{
space->sinkpad = gst_pad_new_from_template (
gst_static_pad_template_get (&gst_hermes_colorspace_sink_pad_template),
"sink");
gst_pad_set_link_function (space->sinkpad, gst_hermes_colorspace_link);
gst_pad_set_getcaps_function (space->sinkpad, gst_hermes_colorspace_getcaps);
gst_pad_set_chain_function(space->sinkpad,gst_hermes_colorspace_chain);
gst_element_add_pad(GST_ELEMENT(space),space->sinkpad);
space->srcpad = gst_pad_new_from_template (
gst_static_pad_template_get (&gst_hermes_colorspace_src_pad_template),
"src");
gst_element_add_pad(GST_ELEMENT(space),space->srcpad);
gst_pad_set_link_function (space->srcpad, gst_hermes_colorspace_link);
space->h_handle = Hermes_ConverterInstance (0);
space->passthru = FALSE;
}
static void
gst_hermes_colorspace_chain (GstPad *pad,GstData *_data)
{
GstBuffer *buf = GST_BUFFER (_data);
GstHermesColorspace *space;
GstBuffer *outbuf = NULL;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
space = GST_HERMES_COLORSPACE (gst_pad_get_parent (pad));
g_return_if_fail (space != NULL);
g_return_if_fail (GST_IS_COLORSPACE (space));
if (space->passthru) {
gst_pad_push (space->srcpad, _data);
return;
}
if (GST_BUFFER_SIZE (buf) < space->sink_size) {
g_critical ("input size is smaller than expected");
}
outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE,
space->src_size);
Hermes_ConverterCopy (space->h_handle,
GST_BUFFER_DATA (buf), 0, 0, space->width, space->height,
space->sink_stride, GST_BUFFER_DATA (outbuf), 0, 0,
space->width, space->height, space->src_stride);
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
gst_buffer_unref (buf);
gst_pad_push (space->srcpad, GST_DATA (outbuf));
}
static GstElementStateReturn
gst_hermes_colorspace_change_state (GstElement *element)
{
GstHermesColorspace *space;
space = GST_HERMES_COLORSPACE (element);
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_PAUSED_TO_PLAYING:
break;
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
break;
}
return parent_class->change_state (element);
}
static void
gst_hermes_colorspace_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
GstHermesColorspace *space;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail(GST_IS_COLORSPACE(object));
space = GST_HERMES_COLORSPACE(object);
switch (prop_id) {
default:
break;
}
}
static void
gst_hermes_colorspace_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
GstHermesColorspace *space;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail(GST_IS_COLORSPACE(object));
space = GST_HERMES_COLORSPACE(object);
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
plugin_init (GstPlugin *plugin)
{
gint hermes_res;
hermes_res = Hermes_Init();
g_return_val_if_fail (hermes_res != 0, FALSE);
if (!gst_element_register (plugin, "hermescolorspace", GST_RANK_PRIMARY,
GST_TYPE_COLORSPACE))
return FALSE;
return TRUE;
}
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"hermescolorspace",
"Hermes colorspace converter",
plugin_init,
VERSION,
"LGPL",
GST_PACKAGE,
GST_ORIGIN)

View file

@ -1,80 +0,0 @@
/*
*
* rgb2rgb.c, Software RGB to YUV convertor
* Written by Nick Kurshev.
* palette & yuv & runtime cpu stuff by Michael (michaelni@gmx.at) (under GPL)
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include <gst/gst.h>
#define Y_FROM_RGB(r,g,b) ((9798 * (r) + 19235 * (g) + 3736 * (b)) >> 15)
#define U_FROM_BY(b,y) ((16122 * ((b) - (y))) >> 15) + 128;
#define V_FROM_RY(r,y) ((25203 * ((r) - (y))) >> 15) + 128;
static void
gst_colorspace_rgb32_to_yuv (unsigned char *src,
unsigned char *ydst,
unsigned char *udst,
unsigned char *vdst,
guint width, guint height)
{
int y;
const int chrom_width = width >> 1;
int Y;
int b, g, r;
for (y = height; y; y -= 2) {
int i;
for (i = chrom_width; i; i--) {
b = *src++;
g = *src++;
r = *src++;
src++;
Y = Y_FROM_RGB (r,g,b);
*ydst++ = Y;
*udst++ = U_FROM_BY (b,Y);
*vdst++ = V_FROM_RY (r,Y);
b = *src++;
g = *src++;
r = *src++; src++;
*ydst++ = Y_FROM_RGB (r,g,b);
}
for (i = width; i; i--) {
b = *src++;
g = *src++;
r = *src++; src++;
*ydst++ = Y_FROM_RGB (r,g,b);
}
}
}
void
gst_colorspace_rgb32_to_i420 (unsigned char *src, unsigned char *dest, guint width, guint height)
{
unsigned char *ydst = dest;
unsigned char *udst = ydst + (width * height);
unsigned char *vdst = udst + ((width * height) >> 2);
gst_colorspace_rgb32_to_yuv (src, ydst, udst, vdst, width, height);
}
void
gst_colorspace_rgb32_to_yv12 (unsigned char *src, unsigned char *dest, guint width, guint height)
{
unsigned char *ydst = dest;
unsigned char *vdst = ydst + (width * height);
unsigned char *udst = vdst + ((width * height) >> 2);
gst_colorspace_rgb32_to_yuv (src, ydst, udst, vdst, width, height);
}

View file

@ -1,188 +0,0 @@
.globl mmx_80w
.data
.align 4
.type mmx_80w,@object
.size mmx_80w,8
mmx_80w:
.long 8388736
.long 8388736
.globl mmx_10w
.align 4
.type mmx_10w,@object
.size mmx_10w,8
mmx_10w:
.long 269488144
.long 269488144
.globl mmx_00ffw
.align 4
.type mmx_00ffw,@object
.size mmx_00ffw,8
mmx_00ffw:
.long 16711935
.long 16711935
.globl mmx_Y_coeff
.align 4
.type mmx_Y_coeff,@object
.size mmx_Y_coeff,8
mmx_Y_coeff:
.long 624895295
.long 624895295
.globl mmx_U_green
.align 4
.type mmx_U_green,@object
.size mmx_U_green,8
mmx_U_green:
.long -209849475
.long -209849475
.globl mmx_U_blue
.align 4
.type mmx_U_blue,@object
.size mmx_U_blue,8
mmx_U_blue:
.long 1083392147
.long 1083392147
.globl mmx_V_red
.align 4
.type mmx_V_red,@object
.size mmx_V_red,8
mmx_V_red:
.long 856830738
.long 856830738
.globl mmx_V_green
.align 4
.type mmx_V_green,@object
.size mmx_V_green,8
mmx_V_green:
.long -436410884
.long -436410884
.globl mmx_redmask
.align 4
.type mmx_redmask,@object
.size mmx_redmask,8
mmx_redmask:
.long -117901064
.long -117901064
.globl mmx_grnmask
.align 4
.type mmx_grnmask,@object
.size mmx_grnmask,8
mmx_grnmask:
.long -50529028
.long -50529028
.text
.align 4
.globl gst_colorspace_yuv_to_bgr16_mmx
.type gst_colorspace_yuv_to_bgr16_mmx,@function
gst_colorspace_yuv_to_bgr16_mmx:
subl $8,%esp
pushl %ebp
pushl %edi
pushl %esi
movl 28(%esp),%edi
movl 32(%esp),%ecx
movl 36(%esp),%edx
movl $1,%ebp
movl 48(%esp),%esi
sarl $1,%esi
movl %esi,16(%esp)
pxor %mm4, %mm4 # zero mm4
movl %esi,12(%esp)
sarl $2,12(%esp)
movl 40(%esp),%esi
.p2align 4,,7
.L68:
movd (%ecx), %mm0 # Load 4 Cb 00 00 00 00 00 u3 u2 u1 u0
movd (%edx), %mm1 # Load 4 Cr 00 00 00 00 00 v2 v1 v0
movq (%edi), %mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
movl 12(%esp),%eax
.p2align 4,,7
.L74:
punpcklbw %mm4, %mm0 # scatter 4 Cb 00 u3 00 u2 00 u1 00 u0
punpcklbw %mm4, %mm1 # scatter 4 Cr 00 v3 00 v2 00 v1 00 v0
psubsw mmx_80w, %mm0 # Cb -= 128
psubsw mmx_80w, %mm1 # Cr -= 128
psllw $3, %mm0 # Promote precision
psllw $3, %mm1 # Promote precision
movq %mm0, %mm2 # Copy 4 Cb 00 u3 00 u2 00 u1 00 u0
movq %mm1, %mm3 # Copy 4 Cr 00 v3 00 v2 00 v1 00 v0
pmulhw mmx_U_green, %mm2 # Mul Cb with green coeff -> Cb green
pmulhw mmx_V_green, %mm3 # Mul Cr with green coeff -> Cr green
pmulhw mmx_U_blue, %mm0 # Mul Cb -> Cblue 00 b3 00 b2 00 b1 00 b0
pmulhw mmx_V_red, %mm1 # Mul Cr -> Cred 00 r3 00 r2 00 r1 00 r0
paddsw %mm3, %mm2 # Cb green + Cr green -> Cgreen
psubusb mmx_10w, %mm6 # Y -= 16
movq %mm6, %mm7 # Copy 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
pand mmx_00ffw, %mm6 # get Y even 00 Y6 00 Y4 00 Y2 00 Y0
psrlw $8, %mm7 # get Y odd 00 Y7 00 Y5 00 Y3 00 Y1
psllw $3, %mm6 # Promote precision
psllw $3, %mm7 # Promote precision
pmulhw mmx_Y_coeff, %mm6 # Mul 4 Y even 00 y6 00 y4 00 y2 00 y0
pmulhw mmx_Y_coeff, %mm7 # Mul 4 Y odd 00 y7 00 y5 00 y3 00 y1
movq %mm0, %mm3 # Copy Cblue
movq %mm1, %mm4 # Copy Cred
movq %mm2, %mm5 # Copy Cgreen
paddsw %mm6, %mm0 # Y even + Cblue 00 B6 00 B4 00 B2 00 B0
paddsw %mm7, %mm3 # Y odd + Cblue 00 B7 00 B5 00 B3 00 B1
paddsw %mm6, %mm1 # Y even + Cred 00 R6 00 R4 00 R2 00 R0
paddsw %mm7, %mm4 # Y odd + Cred 00 R7 00 R5 00 R3 00 R1
paddsw %mm6, %mm2 # Y even + Cgreen 00 G6 00 G4 00 G2 00 G0
paddsw %mm7, %mm5 # Y odd + Cgreen 00 G7 00 G5 00 G3 00 G1
packuswb %mm0, %mm0 # B6 B4 B2 B0 | B6 B4 B2 B0
packuswb %mm1, %mm1 # R6 R4 R2 R0 | R6 R4 R2 R0
packuswb %mm2, %mm2 # G6 G4 G2 G0 | G6 G4 G2 G0
packuswb %mm3, %mm3 # B7 B5 B3 B1 | B7 B5 B3 B1
packuswb %mm4, %mm4 # R7 R5 R3 R1 | R7 R5 R3 R1
packuswb %mm5, %mm5 # G7 G5 G3 G1 | G7 G5 G3 G1
punpcklbw %mm3, %mm0 # B7 B6 B5 B4 B3 B2 B1 B0
punpcklbw %mm4, %mm1 # R7 R6 R5 R4 R3 R2 R1 R0
punpcklbw %mm5, %mm2 # G7 G6 G5 G4 G3 G2 G1 G0
pand mmx_redmask, %mm0 # b7b6b5b4 b3_0_0_0 b7b6b5b4 b3_0_0_0
pand mmx_grnmask, %mm2 # g7g6g5g4 g3g2_0_0 g7g6g5g4 g3g2_0_0
pand mmx_redmask, %mm1 # r7r6r5r4 r3_0_0_0 r7r6r5r4 r3_0_0_0
psrlw $3,%mm0 #0_0_0_b7 b6b5b4b3 0_0_0_b7 b6b5b4b3
pxor %mm4, %mm4 # zero mm4
movq %mm0, %mm5 # Copy B7-B0
movq %mm2, %mm7 # Copy G7-G0
punpcklbw %mm4, %mm2 # 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0
punpcklbw %mm1, %mm0 # r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3
psllw $3,%mm2 # 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0
por %mm2, %mm0 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3
movq 8(%edi), %mm6 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
movq %mm0, (%esi) # store pixel 0-3
punpckhbw %mm4, %mm7 # 0_0_0_0 0_0_0_0 g7g6g5g4 g3g2_0_0
punpckhbw %mm1, %mm5 # r7r6r5r4 r3_0_0_0 0_0_0_b7 b6b5b4b3
psllw $3,%mm7 # 0_0_0_0 0_g7g6g5 g4g3g2_0 0_0_0_0
movd 4(%ecx), %mm0 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0
por %mm7, %mm5 # r7r6r5r4 r3g7g6g5 g4g3g2b7 b6b5b4b3
movd 4(%edx), %mm1 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0
movq %mm5, 8(%esi) # store pixel 4-7
addl $8,%edi
addl $4,%ecx
addl $4,%edx
addl $16,%esi
decl %eax
jnz .L74
.L72:
xorl $1,%ebp
jne .L76
subl 16(%esp),%ecx
subl 16(%esp),%edx
.L76:
subl $1,44(%esp)
jnz .L68
emms
popl %esi
popl %edi
popl %ebp
addl $8,%esp
ret

View file

@ -1,79 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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.
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <gst/gst.h>
/*#undef HAVE_LIBMMX */
#ifdef HAVE_LIBMMX
#include "mmx.h"
#endif
void gst_colorspace_yuy2_to_i420(unsigned char *src, unsigned char *dest, guint width, guint height)
{
int size, i, j;
guchar *desty, *destr, *destb;
size = width * height;
desty = dest;
destr = desty + size;
destb = destr + (size>>2);
for (i=0; i<height; i++) {
for (j=0; j<(width>>1); j++) {
*desty++ = *src;
*desty++ = *(src+2);
if ((i&1) == 0) {
*destr++ = *(src+1);
*destb++ = *(src+3);
}
src += 4;
}
}
}
void gst_colorspace_i420_to_yv12(unsigned char *src, unsigned char *dest, guint width, guint height)
{
int size, i;
guint8 *destcr, *destcb;
size = width * height;
memcpy (dest, src, size);
src += size;
destcr = dest + size;
size >>=2;
destcb = destcr + size;
i=size;
while (i--)
*destcb++ = *src++;
i=size;
while (i--)
*destcr++ = *src++;
}

View file

@ -1,29 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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 __YUV2YUV_H__
#define __YUV2YUV_H__
#include <gst/gst.h>
void gst_colorspace_yuy2_to_i420 (guchar *src, guchar *dest, guint width, guint height);
void gst_colorspace_i420_to_yv12 (guchar *src, guchar *dest, guint width, guint height);
#endif

View file

@ -0,0 +1,15 @@
plugin_LTLIBRARIES = libgstcolorspace.la
if HAVE_CPU_I386
ARCHSRCS = yuv2rgb_mmx16.s
else
ARCHSRCS =
endif
libgstcolorspace_la_SOURCES = gstcolorspace.c yuv2rgb.c yuv2yuv.c
libgstcolorspace_la_CFLAGS = $(GST_CFLAGS)
libgstcolorspace_la_LIBADD =
libgstcolorspace_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
#noinst_HEADERS = yuv2rgb.h yuv2yuv.h

View file

@ -20,21 +20,56 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gstcolorspace.h>
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstcolorspace.h"
#include "yuv2rgb.h"
#include "yuv2yuv.h"
static GstElementDetails colorspace_details = {
"Colorspace converter",
"Filter/Converter/Video",
"Converts video from one colorspace to another using libhermes",
"Wim Taymans <wim.taymans@chello.be>",
static GstColorspaceFormat gst_colorspace_formats[] = {
{ GST_STATIC_CAPS (GST_VIDEO_YUV_PAD_TEMPLATE_CAPS("I420")) },
{ GST_STATIC_CAPS (GST_VIDEO_YUV_PAD_TEMPLATE_CAPS("YV12")) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_32) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24) },
{ GST_STATIC_CAPS (GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_16) },
};
static GstColorspaceConverter gst_colorspace_converters[] = {
{ GST_COLORSPACE_I420, GST_COLORSPACE_RGB32, gst_colorspace_I420_to_rgb32 },
{ GST_COLORSPACE_YV12, GST_COLORSPACE_RGB32, gst_colorspace_YV12_to_rgb32 },
{ GST_COLORSPACE_I420, GST_COLORSPACE_RGB24, gst_colorspace_I420_to_rgb24 },
{ GST_COLORSPACE_YV12, GST_COLORSPACE_RGB24, gst_colorspace_YV12_to_rgb24 },
{ GST_COLORSPACE_I420, GST_COLORSPACE_RGB16, gst_colorspace_I420_to_rgb16 },
{ GST_COLORSPACE_YV12, GST_COLORSPACE_RGB16, gst_colorspace_YV12_to_rgb16 },
};
static GstElementDetails colorspace_details = GST_ELEMENT_DETAILS (
"Colorspace converter",
"Filter/Converter/Video",
"Converts video from one colorspace to another",
"Wim Taymans <wim.taymans@chello.be>"
);
static GstStaticPadTemplate gst_colorspace_sink_template =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_YUV_PAD_TEMPLATE_CAPS ("{ I420, YV12 }"))
);
static GstStaticPadTemplate gst_colorspace_src_template =
GST_STATIC_PAD_TEMPLATE (
"src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_32 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24 "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_16
)
);
/* Stereo signals and args */
enum {
@ -63,16 +98,11 @@ static void gst_colorspace_chain (GstPad *pad, GstData *_data);
static GstElementStateReturn
gst_colorspace_change_state (GstElement *element);
/* FIXME */
extern void gst_colorspace_rgb32_to_i420 (unsigned char *src, unsigned char *dest,
guint width, guint height);
extern void gst_colorspace_rgb32_to_yv12 (unsigned char *src, unsigned char *dest,
guint width, guint height);
static GstPadTemplate *srctempl, *sinktempl;
static GstElementClass *parent_class = NULL;
/*static guint gst_colorspace_signals[LAST_SIGNAL] = { 0 }; */
#if 0
static gboolean
colorspace_setup_converter (GstColorspace *space, GstCaps *from_caps, GstCaps *to_caps)
{
@ -225,26 +255,128 @@ colorspace_setup_converter (GstColorspace *space, GstCaps *from_caps, GstCaps *t
}
return FALSE;
}
#endif
static GstCaps *
gst_colorspace_caps_remove_format_info (GstCaps *caps, const char *media_type)
{
int i;
GstStructure *structure;
GstCaps *rgbcaps;
for (i=0; i<gst_caps_get_size (caps); i++) {
structure = gst_caps_get_structure (caps, i);
gst_structure_set_name (structure, media_type);
gst_structure_remove_field (structure, "format");
gst_structure_remove_field (structure, "endianness");
gst_structure_remove_field (structure, "depth");
gst_structure_remove_field (structure, "bpp");
gst_structure_remove_field (structure, "red_mask");
gst_structure_remove_field (structure, "green_mask");
gst_structure_remove_field (structure, "blue_mask");
}
rgbcaps = gst_caps_simplify (caps);
gst_caps_free (caps);
return rgbcaps;
}
static GstCaps*
gst_colorspace_getcaps (GstPad *pad)
{
GstColorspace *space;
GstCaps *peercaps;
GstCaps *ourcaps;
GstPad *otherpad;
GstCaps *othercaps;
GstCaps *caps;
space = GST_COLORSPACE (gst_pad_get_parent (pad));
/* we can do everything our peer can... */
peercaps = gst_pad_get_allowed_caps (space->srcpad);
otherpad = (pad == space->srcpad) ? space->sinkpad : space->srcpad;
/* and our own template of course */
ourcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
othercaps = gst_pad_get_allowed_caps (otherpad);
/* merge them together, we prefer the peercaps first */
gst_caps_append (peercaps, ourcaps);
othercaps = gst_colorspace_caps_remove_format_info (othercaps,
(pad == space->srcpad) ? "video/x-raw-rgb" : "video/x-raw-yuv");
return peercaps;
caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
gst_caps_free (othercaps);
return caps;
}
static GstColorSpaceFormatType
gst_colorspace_get_format (const GstCaps *caps)
{
int i;
for(i=0; i<G_N_ELEMENTS (gst_colorspace_formats); i++) {
GstCaps *icaps;
GstCaps *fcaps;
fcaps = gst_caps_copy (gst_static_caps_get (
&gst_colorspace_formats[i].caps));
icaps = gst_caps_intersect (caps, fcaps);
if (!gst_caps_is_empty (icaps)) {
gst_caps_free (icaps);
return i;
}
gst_caps_free (icaps);
}
g_assert_not_reached();
return -1;
}
#define ROUND_UP_2(x) (((x)+1)&~1)
#define ROUND_UP_4(x) (((x)+3)&~3)
#define ROUND_UP_8(x) (((x)+7)&~7)
static int
gst_colorspace_format_get_size(GstColorSpaceFormatType index, int width,
int height)
{
int size;
switch (index) {
case GST_COLORSPACE_I420:
case GST_COLORSPACE_YV12:
size = ROUND_UP_4 (width) * ROUND_UP_2 (height);
size += ROUND_UP_8 (width)/2 * ROUND_UP_2 (height)/2;
size += ROUND_UP_8 (width)/2 * ROUND_UP_2 (height)/2;
return size;
break;
case GST_COLORSPACE_RGB32:
return width*height*4;
break;
case GST_COLORSPACE_RGB24:
return ROUND_UP_4 (width*3) * height;
break;
case GST_COLORSPACE_RGB16:
return ROUND_UP_4 (width*2) * height;
break;
}
g_assert_not_reached();
return 0;
}
static int
gst_colorspace_get_converter (GstColorSpaceFormatType from,
GstColorSpaceFormatType to)
{
int i;
for (i=0; i<G_N_ELEMENTS (gst_colorspace_converters); i++) {
GstColorspaceConverter *converter = gst_colorspace_converters + i;
if (from == converter->from && to == converter->to) {
return i;
}
}
g_assert_not_reached();
return -1;
}
static GstPadLinkReturn
@ -253,42 +385,75 @@ gst_colorspace_link (GstPad *pad, const GstCaps *caps)
GstColorspace *space;
GstPad *otherpad;
GstStructure *structure;
GstPadLinkReturn link_ret;
int width, height;
double fps;
int format_index;
space = GST_COLORSPACE (gst_pad_get_parent (pad));
otherpad = (pad == space->sinkpad) ? space->srcpad : space->sinkpad;
link_ret = gst_pad_try_set_caps (otherpad, caps);
if (link_ret == GST_PAD_LINK_OK) {
return link_ret;
}
structure = gst_caps_get_structure (caps, 0);
gst_structure_get_int (structure, "width", &space->width);
gst_structure_get_int (structure, "height", &space->height);
gst_structure_get_double (structure, "framerate", &space->fps);
format_index = gst_colorspace_get_format (caps);
g_print("format index is %d\n", format_index);
gst_structure_get_int (structure, "width", &width);
gst_structure_get_int (structure, "height", &height);
gst_structure_get_double (structure, "framerate", &fps);
GST_INFO ( "size: %dx%d", space->width, space->height);
if (pad == space->sinkpad) {
gst_caps_replace (&space->sinkcaps, gst_caps_copy(caps));
if (gst_pad_is_negotiated (otherpad)) {
GstCaps *othercaps;
othercaps = gst_caps_copy (gst_pad_get_negotiated_caps (otherpad));
gst_caps_set_simple (othercaps,
"width", G_TYPE_INT, width,
"height", G_TYPE_INT, height,
"framerate", G_TYPE_DOUBLE, fps, NULL);
link_ret = gst_pad_try_set_caps (otherpad, othercaps);
if (link_ret != GST_PAD_LINK_OK) {
return link_ret;
}
}
if (pad == space->srcpad) {
space->src_format_index = format_index;
} else {
gst_caps_replace (&space->srccaps, gst_caps_copy(caps));
space->sink_format_index = format_index;
}
if (gst_pad_is_negotiated (otherpad)) {
space->converter_index = gst_colorspace_get_converter (
space->sink_format_index, space->src_format_index);
g_print("using index %d\n", space->converter_index);
space->sink_size = gst_colorspace_format_get_size(space->sink_format_index,
width,height);
space->src_size = gst_colorspace_format_get_size(space->src_format_index,
width,height);
space->width = width;
space->height = height;
space->fps = fps;
}
#if 0
peer = gst_pad_get_peer (otherpad);
if (!peer) {
return GST_PAD_LINK_DELAYED;
if (gst_pad_is_negotiated (otherpad)) {
g_warning ("could not get converter\n");
return GST_PAD_LINK_REFUSED;
}
#endif
if (gst_pad_try_set_caps (otherpad, caps) >= 0) {
space->passthru = TRUE;
return GST_PAD_LINK_OK;
}
if (colorspace_setup_converter (space, space->sinkcaps, space->srccaps)) {
return GST_PAD_LINK_OK;
}
return GST_PAD_LINK_REFUSED;
return GST_PAD_LINK_OK;
}
GType
@ -317,31 +482,12 @@ static void
gst_colorspace_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstCaps *caps;
/* create caps for templates */
caps = gst_caps_from_string (
GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2 }") "; "
GST_VIDEO_CAPS_RGB "; "
GST_VIDEO_CAPS_BGR "; "
GST_VIDEO_CAPS_xBGR "; "
GST_VIDEO_CAPS_xRGB "; "
GST_VIDEO_CAPS_BGRx "; "
GST_VIDEO_CAPS_RGBx "; "
GST_VIDEO_CAPS_RGB_15 "; "
GST_VIDEO_CAPS_RGB_16);
/* build templates */
srctempl = gst_pad_template_new ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
caps);
sinktempl = gst_pad_template_new ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
caps);
gst_element_class_add_pad_template (element_class, srctempl);
gst_element_class_add_pad_template (element_class, sinktempl);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_colorspace_src_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_colorspace_sink_template));
gst_element_class_set_details (element_class, &colorspace_details);
}
@ -360,26 +506,26 @@ gst_colorspace_class_init (GstColorspaceClass *klass)
gobject_class->get_property = gst_colorspace_get_property;
gstelement_class->change_state = gst_colorspace_change_state;
gst_colorspace_table_init(NULL);
}
static void
gst_colorspace_init (GstColorspace *space)
{
space->sinkpad = gst_pad_new_from_template (sinktempl, "sink");
space->sinkpad = gst_pad_new_from_template (
gst_static_pad_template_get (&gst_colorspace_sink_template),
"sink");
gst_pad_set_link_function (space->sinkpad, gst_colorspace_link);
gst_pad_set_getcaps_function (space->sinkpad, gst_colorspace_getcaps);
gst_pad_set_chain_function(space->sinkpad,gst_colorspace_chain);
gst_element_add_pad(GST_ELEMENT(space),space->sinkpad);
space->srcpad = gst_pad_new_from_template (srctempl, "src");
space->srcpad = gst_pad_new_from_template (
gst_static_pad_template_get (&gst_colorspace_src_template),
"src");
gst_element_add_pad(GST_ELEMENT(space),space->srcpad);
gst_pad_set_link_function (space->srcpad, gst_colorspace_link);
#ifdef HAVE_HERMES
space->h_handle = Hermes_ConverterInstance (0);
#endif
space->converter = NULL;
space->passthru = FALSE;
}
static void
@ -387,9 +533,8 @@ gst_colorspace_chain (GstPad *pad,GstData *_data)
{
GstBuffer *buf = GST_BUFFER (_data);
GstColorspace *space;
gint size;
GstBuffer *outbuf = NULL;
gint dest_bytes, src_bytes;
GstColorspaceConverter *converter;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
@ -400,54 +545,19 @@ gst_colorspace_chain (GstPad *pad,GstData *_data)
g_return_if_fail (space != NULL);
g_return_if_fail (GST_IS_COLORSPACE (space));
if (space->passthru) {
gst_pad_push (space->srcpad, _data);
return;
if (GST_BUFFER_SIZE (buf) < space->sink_size) {
g_critical ("input size is smaller than expected");
}
size = space->width * space->height;
dest_bytes = ((space->destbpp+7)/8);
src_bytes = ((space->srcbpp+7)/8);
outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE,
(size * space->destbpp)/8);
space->src_size);
if (space->type == GST_COLORSPACE_YUV_RGB) {
gst_colorspace_convert (space->converter, GST_BUFFER_DATA (buf), GST_BUFFER_DATA (outbuf));
}
#ifdef HAVE_HERMES
else if (space->type == GST_COLORSPACE_HERMES) {
Hermes_ConverterCopy (space->h_handle,
GST_BUFFER_DATA (buf), 0, 0, space->width, space->height, space->width * src_bytes,
GST_BUFFER_DATA (outbuf), 0, 0, space->width, space->height, space->width * dest_bytes);
}
#endif
else if (space->type == GST_COLORSPACE_YUY2_I420) {
gst_colorspace_yuy2_to_i420 (GST_BUFFER_DATA (buf),
GST_BUFFER_DATA (outbuf),
space->width,
space->height);
}
else if (space->type == GST_COLORSPACE_420_SWAP) {
gst_colorspace_i420_to_yv12 (GST_BUFFER_DATA (buf),
GST_BUFFER_DATA (outbuf),
space->width,
space->height);
}
else if (space->type == GST_COLORSPACE_RGB32_I420) {
gst_colorspace_rgb32_to_i420 (GST_BUFFER_DATA (buf),
GST_BUFFER_DATA (outbuf),
space->width,
space->height);
}
else if (space->type == GST_COLORSPACE_RGB32_YV12) {
gst_colorspace_rgb32_to_yv12 (GST_BUFFER_DATA (buf),
GST_BUFFER_DATA (outbuf),
space->width,
space->height);
}
converter = gst_colorspace_converters + space->converter_index;
converter->convert (space, GST_BUFFER_DATA (outbuf),
GST_BUFFER_DATA (buf));
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
gst_buffer_unref (buf);
gst_pad_push (space->srcpad, GST_DATA (outbuf));
@ -466,10 +576,6 @@ gst_colorspace_change_state (GstElement *element)
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
gst_colorspace_converter_destroy (space->converter);
space->converter = NULL;
space->type = GST_COLORSPACE_NONE;
gst_caps_replace (&space->sinkcaps, NULL);
break;
}
@ -510,14 +616,8 @@ gst_colorspace_get_property (GObject *object, guint prop_id, GValue *value, GPar
static gboolean
plugin_init (GstPlugin *plugin)
{
#ifdef HAVE_HERMES
gint hermes_res;
hermes_res = Hermes_Init();
g_return_val_if_fail (hermes_res != 0, FALSE);
#endif
if (!gst_element_register (plugin, "colorspace", GST_RANK_PRIMARY, GST_TYPE_COLORSPACE))
if (!gst_element_register (plugin, "colorspace", GST_RANK_PRIMARY,
GST_TYPE_COLORSPACE))
return FALSE;
return TRUE;

View file

@ -17,25 +17,12 @@
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_COLORSPACE_H__
#define __GST_COLORSPACE_H__
#ifndef _GST_COLORSPACE_H_
#define _GST_COLORSPACE_H_
#include <gst/gst.h>
#include "yuv2rgb.h"
#ifdef HAVE_HERMES
# include <Hermes/Hermes.h>
#endif
/* #include <gst/meta/audioraw.h> */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
G_BEGIN_DECLS
#define GST_TYPE_COLORSPACE \
(gst_colorspace_get_type())
@ -66,21 +53,19 @@ struct _GstColorspace {
GstPad *sinkpad,*srcpad;
#ifdef HAVE_HERMES
HermesHandle h_handle;
HermesFormat source, dest;
#endif
int converter_index;
GstColorSpaceConverter *converter;
int src_format_index;
int sink_format_index;
int src_size;
int sink_size;
int src_stride;
int sink_stride;
GstColorSpaceConverterType type;
gint width, height;
gdouble fps;
gint srcbpp, destbpp;
gboolean passthru;
GstCaps *sinkcaps;
GstCaps *srccaps;
};
struct _GstColorspaceClass {
@ -89,9 +74,26 @@ struct _GstColorspaceClass {
GType gst_colorspace_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
typedef struct _GstColorspaceFormat {
GstStaticCaps caps;
} GstColorspaceFormat;
typedef enum {
GST_COLORSPACE_I420,
GST_COLORSPACE_YV12,
GST_COLORSPACE_RGB32,
GST_COLORSPACE_RGB24,
GST_COLORSPACE_RGB16,
} GstColorSpaceFormatType;
typedef struct _GstColorspaceConverter {
GstColorSpaceFormatType from;
GstColorSpaceFormatType to;
void (*convert) (GstColorspace *colorspace, unsigned char *dest, unsigned char *src);
} GstColorspaceConverter;
G_END_DECLS
#endif
#endif /* __GST_COLORSPACE_H */

View file

@ -17,19 +17,26 @@
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdlib.h>
#include "yuv2rgb.h"
/* #define HAVE_LIBMMX */
#undef HAVE_LIBMMX
#ifdef HAVE_LIBMMX
#include <mmx.h>
#endif
static int V_r_tab [256];
static int V_g_tab [256];
static int U_g_tab [256];
static int U_b_tab [256];
#define CB_BASE 1
#define CR_BASE (CB_BASE*CB_RANGE)
#define LUM_BASE (CR_BASE*CR_RANGE)
@ -52,215 +59,175 @@
: Max(-128.0, ((x) * chromaCorrect)))
static void gst_colorspace_I420_to_rgb16 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_I420_to_rgb24 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_I420_to_rgb32 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_rgb16 (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_rgb24 (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_rgb32 (GstColorspace *space, unsigned char *src, unsigned char *dest);
#ifdef HAVE_LIBMMX
static void gst_colorspace_I420_to_bgr16_mmx (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_I420_to_bgr32_mmx (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_bgr16_mmx (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_bgr32_mmx (GstColorspace *space, unsigned char *src, unsigned char *dest);
#endif
static void gst_colorspace_YV12_to_rgb16 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_YV12_to_rgb24 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_YV12_to_rgb32 (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb16 (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb24 (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb32 (GstColorspace *space, unsigned char *src, unsigned char *dest);
#ifdef HAVE_LIBMMX
static void gst_colorspace_YV12_to_bgr16_mmx (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
static void gst_colorspace_YV12_to_bgr32_mmx (GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_bgr16_mmx (GstColorspace *space, unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_bgr32_mmx (GstColorspace *space, unsigned char *src, unsigned char *dest);
#endif
static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
static void
gst_colorspace_yuv_to_rgb16(GstColorspace *space,
unsigned char *out,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
int cols, int rows);
static void
gst_colorspace_yuv_to_rgb24(GstColorspace *space,
unsigned char *out,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
int cols, int rows);
static void
gst_colorspace_yuv_to_rgb32(GstColorspace *space,
unsigned char *out,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
int cols, int rows);
#if 0
static void gst_colorspace_yuv_to_rgb16(GstColorspaceYUVTables *tables,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
static void gst_colorspace_yuv_to_rgb24(GstColorSpaceYUVTables *tables,
static void gst_colorspace_yuv_to_rgb24(GstColorspaceYUVTables *tables,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
static void gst_colorspace_yuv_to_rgb32(GstColorSpaceYUVTables *tables,
static void gst_colorspace_yuv_to_rgb32(GstColorspaceYUVTables *tables,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
#ifdef HAVE_LIBMMX
static void gst_colorspace_yuv_to_bgr32_mmx(GstColorSpaceYUVTables *tables,
void gst_colorspace_yuv_to_bgr32_mmx(GstColorspaceYUVTables *tables,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
extern void gst_colorspace_yuv_to_bgr16_mmx(GstColorSpaceYUVTables *tables,
extern void gst_colorspace_yuv_to_bgr16_mmx(GstColorspaceYUVTables *tables,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
#endif
#endif
static GstColorSpaceYUVTables * gst_colorspace_init_yuv(long depth,
long red_mask, long green_mask, long blue_mask);
#define ROUND_UP_2(x) (((x)+1)&~1)
#define ROUND_UP_4(x) (((x)+3)&~3)
#define ROUND_UP_8(x) (((x)+7)&~7)
GstColorSpaceConverter*
gst_colorspace_yuv2rgb_get_converter (const GstCaps *from, const GstCaps *to)
void gst_colorspace_I420_to_rgb32(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
guint32 from_space;
GstColorSpaceConverter *new;
gint to_bpp;
GstStructure *struct_from, *struct_to;
GST_DEBUG ("gst_colorspace_yuv2rgb_get_converter");
unsigned char *src_U;
unsigned char *src_V;
new = g_malloc (sizeof (GstColorSpaceConverter));
src_U = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_V = src_U + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
struct_from = gst_caps_get_structure (from, 0);
struct_to = gst_caps_get_structure (to, 0);
gst_structure_get_int (struct_from, "width", &new->width);
gst_structure_get_int (struct_from, "height", &new->height);
new->color_tables = NULL;
gst_structure_get_fourcc (struct_from, "format", &from_space);
gst_structure_get_int (struct_to, "bpp", &to_bpp);
/* FIXME we leak new here. */
switch(from_space) {
case GST_MAKE_FOURCC ('Y','V','1','2'):
case GST_MAKE_FOURCC ('I','4','2','0'):
{
gint red_mask;
gint green_mask;
gint blue_mask;
gst_structure_get_int (struct_to, "red_mask", &red_mask);
gst_structure_get_int (struct_to, "green_mask", &green_mask);
gst_structure_get_int (struct_to, "blue_mask", &blue_mask);
GST_INFO ( "red_mask %08x", red_mask);
GST_INFO ( "green_mask %08x", green_mask);
GST_INFO ( "blue_mask %08x", blue_mask);
new->insize = new->width * new->height + new->width * new->height/2;
new->color_tables = gst_colorspace_init_yuv (to_bpp, red_mask, green_mask, blue_mask);
new->outsize = new->width * new->height * (to_bpp/8);
switch(to_bpp) {
case 32:
#ifdef HAVE_LIBMMX
if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff &&
(gst_cpu_get_flags () & GST_CPU_FLAG_MMX) ) {
if (from_space == GST_STR_FOURCC ("I420"))
new->convert = gst_colorspace_I420_to_bgr32_mmx;
else
new->convert = gst_colorspace_YV12_to_bgr32_mmx;
}
else
#endif
if (from_space == GST_STR_FOURCC ("I420"))
new->convert = gst_colorspace_I420_to_rgb32;
else
new->convert = gst_colorspace_YV12_to_rgb32;
break;
case 24:
if (from_space == GST_STR_FOURCC ("I420"))
new->convert = gst_colorspace_I420_to_rgb24;
else
new->convert = gst_colorspace_YV12_to_rgb24;
break;
case 15:
case 16:
#ifdef HAVE_LIBMMX
if (red_mask == 0xf800 && green_mask == 0x07e0 && blue_mask == 0x001f &&
(gst_cpu_get_flags () & GST_CPU_FLAG_MMX) ) {
if (from_space == GST_STR_FOURCC ("I420"))
new->convert = gst_colorspace_I420_to_bgr16_mmx;
else
new->convert = gst_colorspace_YV12_to_bgr16_mmx;
}
else
#endif
if (from_space == GST_STR_FOURCC ("I420"))
new->convert = gst_colorspace_I420_to_rgb16;
else
new->convert = gst_colorspace_YV12_to_rgb16;
break;
default:
g_print("gst_colorspace_yuv2rgb not implemented\n");
g_free (new);
new = NULL;
}
break;
}
default:
g_print("gst_colorspace_yuv2rgb not implemented\n");
g_free (new);
new = NULL;
}
return new;
gst_colorspace_yuv_to_rgb32(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
void
gst_colorspace_converter_destroy (GstColorSpaceConverter *conv)
void gst_colorspace_I420_to_rgb24(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
if (conv)
g_free (conv);
unsigned char *src_U;
unsigned char *src_V;
src_U = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_V = src_U + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
gst_colorspace_yuv_to_rgb24(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
static void gst_colorspace_I420_to_rgb32(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest)
void gst_colorspace_I420_to_rgb16(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
int size;
GST_DEBUG ("gst_colorspace_I420_to_rgb32");
unsigned char *src_U;
unsigned char *src_V;
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);
src_U = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_V = src_U + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
gst_colorspace_yuv_to_rgb16(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
static void gst_colorspace_I420_to_rgb24(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_I420_to_rgb24");
void gst_colorspace_YV12_to_rgb32(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
unsigned char *src_U;
unsigned char *src_V;
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);
src_V = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_U = src_V + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
gst_colorspace_yuv_to_rgb32(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
static void gst_colorspace_I420_to_rgb16(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_I420_to_rgb16");
void gst_colorspace_YV12_to_rgb24(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
unsigned char *src_U;
unsigned char *src_V;
size = space->width * space->height;
src_V = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_U = src_V + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
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);
gst_colorspace_yuv_to_rgb24(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
void gst_colorspace_YV12_to_rgb16(GstColorspace *space, unsigned char *dest,
unsigned char *src)
{
unsigned char *src_U;
unsigned char *src_V;
src_V = src + ROUND_UP_4 (space->width) * ROUND_UP_2 (space->height);
src_U = src_V + ROUND_UP_8 (space->width)/2 * ROUND_UP_2 (space->height)/2;
gst_colorspace_yuv_to_rgb16(space,
dest,
src, src_U, src_V,
space->width, space->height);
}
#ifdef HAVE_LIBMMX
static void gst_colorspace_I420_to_bgr32_mmx(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
void gst_colorspace_I420_to_bgr32_mmx(GstColorspace *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_I420_to_rgb32_mmx");
@ -275,7 +242,8 @@ static void gst_colorspace_I420_to_bgr32_mmx(GstColorSpaceConverter *space, unsi
space->width);
}
static void gst_colorspace_I420_to_bgr16_mmx(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
void gst_colorspace_I420_to_bgr16_mmx(GstColorspace *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_I420_to_bgr16_mmx ");
@ -291,60 +259,8 @@ static void gst_colorspace_I420_to_bgr16_mmx(GstColorSpaceConverter *space, unsi
GST_DEBUG ("gst_colorspace_I420_to_bgr16_mmx done");
}
#endif
static void gst_colorspace_YV12_to_rgb32(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest)
{
int size;
GST_DEBUG ("gst_colorspace_YV12_to_rgb32");
size = space->width * space->height;
gst_colorspace_yuv_to_rgb32(space->color_tables,
src, /* Y component */
src+size+(size>>2), /* cb component */
src+size, /* cr component */
dest,
space->height,
space->width);
}
static void gst_colorspace_YV12_to_rgb24(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_YV12_to_rgb24");
size = space->width * space->height;
gst_colorspace_yuv_to_rgb24(space->color_tables,
src, /* Y component */
src+size+(size>>2), /* cb component */
src+size, /* cr component */
dest,
space->height,
space->width);
}
static void gst_colorspace_YV12_to_rgb16(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_YV12_to_rgb16");
size = space->width * space->height;
gst_colorspace_yuv_to_rgb16(space->color_tables,
src, /* Y component */
src+size+(size>>2), /* cb component */
src+size, /* cr component */
dest,
space->height,
space->width);
}
#ifdef HAVE_LIBMMX
static void gst_colorspace_YV12_to_bgr32_mmx(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
void gst_colorspace_YV12_to_bgr32_mmx(GstColorspace *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_YV12_to_rgb32_mmx");
@ -359,7 +275,8 @@ static void gst_colorspace_YV12_to_bgr32_mmx(GstColorSpaceConverter *space, unsi
space->width);
}
static void gst_colorspace_YV12_to_bgr16_mmx(GstColorSpaceConverter *space, unsigned char *src, unsigned char *dest) {
void gst_colorspace_YV12_to_bgr16_mmx(GstColorspace *space, unsigned char *src, unsigned char *dest) {
int size;
GST_DEBUG ("gst_colorspace_YV12_to_bgr16_mmx ");
@ -436,21 +353,33 @@ unsigned long a;
*--------------------------------------------------------------
*/
static GstColorSpaceYUVTables *
gst_colorspace_init_yuv(long depth, long red_mask, long green_mask, long blue_mask)
void
gst_colorspace_table_init (GstColorspace *space)
{
int i;
for (i=0; i<256; i++) {
V_r_tab[i] = (0.419/0.299) * (i-128);
V_g_tab[i] = -(0.299/0.419) * (i-128);
U_g_tab[i] = -(0.114/0.331) * (i-128);
U_b_tab[i] = (0.587/0.331) * (i-128);
}
#if 0
int CR, CB, i;
int *L_tab, *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
long *r_2_pix_alloc;
long *g_2_pix_alloc;
long *b_2_pix_alloc;
GstColorSpaceYUVTables *tables = g_malloc(sizeof(GstColorSpaceYUVTables));
long depth = 32;
long red_mask = 0xff0000;
long green_mask = 0x00ff00;
long blue_mask = 0x0000ff;
L_tab = tables->L_tab = (int *)malloc(256*sizeof(int));
Cr_r_tab = tables->Cr_r_tab = (int *)malloc(256*sizeof(int));
Cr_g_tab = tables->Cr_g_tab = (int *)malloc(256*sizeof(int));
Cb_g_tab = tables->Cb_g_tab = (int *)malloc(256*sizeof(int));
Cb_b_tab = tables->Cb_b_tab = (int *)malloc(256*sizeof(int));
L_tab = space->L_tab = (int *)malloc(256*sizeof(int));
Cr_r_tab = space->Cr_r_tab = (int *)malloc(256*sizeof(int));
Cr_g_tab = space->Cr_g_tab = (int *)malloc(256*sizeof(int));
Cb_g_tab = space->Cb_g_tab = (int *)malloc(256*sizeof(int));
Cb_b_tab = space->Cb_b_tab = (int *)malloc(256*sizeof(int));
r_2_pix_alloc = (long *)malloc(768*sizeof(long));
g_2_pix_alloc = (long *)malloc(768*sizeof(long));
@ -546,234 +475,100 @@ gst_colorspace_init_yuv(long depth, long red_mask, long green_mask, long blue_ma
b_2_pix_alloc[i+ 512] = b_2_pix_alloc[511];
}
tables->r_2_pix = r_2_pix_alloc + 256;
tables->g_2_pix = g_2_pix_alloc + 256;
tables->b_2_pix = b_2_pix_alloc + 256;
return tables;
}
/*
*--------------------------------------------------------------
*
* Color16DitherImage --
*
* Converts image into 16 bit color.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
gst_colorspace_yuv_to_rgb16(tables, lum, cb, cr, out, rows, cols)
GstColorSpaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
{
int L, CR, CB;
unsigned short *row1, *row2;
unsigned char *lum2;
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols>>1;
row1 = (unsigned short *)out;
row2 = row1 + cols;
lum2 = lum + cols;
for (y=rows>>1; y; y--) {
for (x=cols_2; x; x--) {
CR = *cr++;
CB = *cb++;
cr_r = tables->Cr_r_tab[CR];
crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
L = tables->L_tab[(int) *lum++];
*row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
L = tables->L_tab[(int) *lum++];
*row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
/*
* Now, do second row.
*/
L = tables->L_tab[(int) *lum2++];
*row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
L = tables->L_tab[(int) *lum2++];
*row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
}
/*
* These values are at the start of the next line, (due
* to the ++'s above),but they need to be at the start
* of the line after that.
*/
lum = lum2;
row1 = row2;
lum2 += cols;
row2 += cols;
}
space->r_2_pix = r_2_pix_alloc + 256;
space->g_2_pix = g_2_pix_alloc + 256;
space->b_2_pix = b_2_pix_alloc + 256;
#endif
}
static void
gst_colorspace_yuv_to_rgb24(tables, lum, cb, cr, out, rows, cols)
GstColorSpaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
gst_colorspace_yuv_to_rgb32(GstColorspace *space,
unsigned char *dest,
unsigned char *Y,
unsigned char *U,
unsigned char *V,
int width, int height)
{
int L, CR, CB;
unsigned char *row1, *row2;
unsigned char *lum2;
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols>>1;
int cols_3 = cols*3;
unsigned char pixels[4];
int x,y;
int src_rowstride;
int dest_rowstride;
row1 = out;
row2 = row1 + cols_3;
lum2 = lum + cols;
for (y=rows>>1; y; y--) {
for (x=cols_2; x; x--) {
CR = *cr++;
CB = *cb++;
cr_r = tables->Cr_r_tab[CR];
crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
L = tables->L_tab[(int) *lum++];
((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
*row1++ = pixels[0]; *row1++ = pixels[1]; *row1++ = pixels[2];
L = tables->L_tab[(int) *lum++];
((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
*row1++ = pixels[0]; *row1++ = pixels[1]; *row1++ = pixels[2];
/*
* Now, do second row.
*/
L = tables->L_tab [(int) *lum2++];
((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
*row2++ = pixels[0]; *row2++ = pixels[1]; *row2++ = pixels[2];
L = tables->L_tab [(int) *lum2++];
((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
*row2++ = pixels[0]; *row2++ = pixels[1]; *row2++ = pixels[2];
}
lum = lum2;
row1 = row2;
lum2 += cols;
row2 += cols_3;
src_rowstride = ROUND_UP_4 (space->width);
dest_rowstride = width * 4;
for(y=0;y<height;y++){
for(x=0;x<width;x++){
dest[x*4 + 0] = 0;
dest[x*3 + 1] = CLAMP (Y[x] + V_r_tab[V[x/2]], 0, 255);
dest[x*3 + 2] = CLAMP (Y[x] + U_g_tab[U[x/2]] + V_g_tab[V[x/2]], 0, 255);
dest[x*3 + 3] = CLAMP (Y[x] + U_b_tab[U[x/2]], 0, 255);
}
Y += src_rowstride;
dest += dest_rowstride;
if (y&1) {
U += src_rowstride/2;
V += src_rowstride/2;
}
}
}
/*
*--------------------------------------------------------------
*
* Color32DitherImage --
*
* Converts image into 32 bit color (or 24-bit non-packed).
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
gst_colorspace_yuv_to_rgb24(GstColorspace *space,
unsigned char *dest,
unsigned char *Y,
unsigned char *U,
unsigned char *V,
int width, int height)
{
int x,y;
int src_rowstride;
int dest_rowstride;
/*
* This is a copysoft version of the function above with ints instead
* of shorts to cause a 4-byte pixel size
*/
src_rowstride = ROUND_UP_4 (space->width);
dest_rowstride = ROUND_UP_4 (width * 3);
for(y=0;y<height;y++){
for(x=0;x<width;x++){
dest[x*3 + 0] = CLAMP (Y[x] + V_r_tab[V[x/2]], 0, 255);
dest[x*3 + 1] = CLAMP (Y[x] + U_g_tab[U[x/2]] + V_g_tab[V[x/2]], 0, 255);
dest[x*3 + 2] = CLAMP (Y[x] + U_b_tab[U[x/2]], 0, 255);
}
Y += src_rowstride;
dest += dest_rowstride;
if (y&1) {
U += src_rowstride/2;
V += src_rowstride/2;
}
}
}
static void
gst_colorspace_yuv_to_rgb32(tables, lum, cb, cr, out, rows, cols)
GstColorSpaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
gst_colorspace_yuv_to_rgb16(GstColorspace *space,
unsigned char *dest,
unsigned char *Y,
unsigned char *U,
unsigned char *V,
int width, int height)
{
int L, CR, CB;
unsigned int *row1, *row2;
unsigned char *lum2;
int x, y;
int cr_r;
int crb_g;
int cb_b;
int cols_2 = cols>>1;
int x,y;
int src_rowstride;
int dest_rowstride;
int r, g, b;
row1 = (guint32 *)out;
row2 = row1 + cols;
lum2 = lum + cols;
for (y=rows>>1; y; y--) {
for (x=cols_2; x; x--) {
CR = *cr++;
CB = *cb++;
cr_r = tables->Cr_r_tab[CR];
crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
L = tables->L_tab[(int) *lum++];
*row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
L = tables->L_tab[(int) *lum++];
*row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
/*
* Now, do second row.
*/
L = tables->L_tab [(int) *lum2++];
*row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
L = tables->L_tab [(int) *lum2++];
*row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
}
lum = lum2;
row1 = row2;
lum2 += cols;
row2 += cols;
src_rowstride = ROUND_UP_4 (space->width);
dest_rowstride = ROUND_UP_4 (width * 2);
for(y=0;y<height;y++){
for(x=0;x<width;x++){
r = CLAMP (Y[x] + V_r_tab[V[x/2]], 0, 255);
g = CLAMP (Y[x] + U_g_tab[U[x/2]] + V_g_tab[V[x/2]], 0, 255);
b = CLAMP (Y[x] + U_b_tab[U[x/2]], 0, 255);
*(unsigned short *)(dest + x*2) = ((r&0xf8)<<8) | ((g&0xfc)<<3) | (b>>3);
}
Y += src_rowstride;
dest += dest_rowstride;
if (y&1) {
U += src_rowstride/2;
V += src_rowstride/2;
}
}
}
#ifdef HAVE_LIBMMX
@ -789,7 +584,7 @@ static mmx_t MMX32_Vgrncoeff = (mmx_t)(long long)0xffd2ffd2ffd2ffd2LL;
static void
gst_colorspace_yuv_to_bgr32_mmx(tables, lum, cr, cb, out, rows, cols)
GstColorSpaceYUVTables *tables;
GstColorspaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;

View file

@ -23,10 +23,14 @@
#define __YUV2RGB_H__
#include <gst/gst.h>
#include <gstcolorspace.h>
typedef struct _GstColorSpaceYUVTables GstColorSpaceYUVTables;
G_BEGIN_DECLS
struct _GstColorSpaceYUVTables {
#if 0
typedef struct _GstColorspaceYUVTables GstColorspaceYUVTables;
struct _GstColorspaceYUVTables {
int gammaCorrectFlag;
double gammaCorrect;
int chromaCorrectFlag;
@ -45,24 +49,49 @@ struct _GstColorSpaceYUVTables {
};
typedef struct _GstColorSpaceConverter GstColorSpaceConverter;
typedef void (*GstColorSpaceConvertFunction) (GstColorSpaceConverter *space, guchar *src, guchar *dest);
typedef struct _GstColorspaceConverter GstColorspaceConverter;
typedef void (*GstColorspaceConvertFunction) (GstColorspaceConverter *space, guchar *src, guchar *dest);
struct _GstColorSpaceConverter {
struct _GstColorspaceConverter {
guint width;
guint height;
guint insize;
guint outsize;
/* private */
GstColorSpaceYUVTables *color_tables;
GstColorSpaceConvertFunction convert;
GstColorspaceYUVTables *color_tables;
GstColorspaceConvertFunction convert;
};
#endif
void gst_colorspace_table_init (GstColorspace *space);
void gst_colorspace_I420_to_rgb32(GstColorspace *space,
unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_rgb24(GstColorspace *space,
unsigned char *src, unsigned char *dest);
void gst_colorspace_I420_to_rgb16(GstColorspace *space,
unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb32(GstColorspace *space,
unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb24(GstColorspace *space,
unsigned char *src, unsigned char *dest);
void gst_colorspace_YV12_to_rgb16(GstColorspace *space,
unsigned char *src, unsigned char *dest);
#if 0
GstColorspaceYUVTables * gst_colorspace_init_yuv(long depth,
long red_mask, long green_mask, long blue_mask);
#endif
GstColorSpaceConverter* gst_colorspace_yuv2rgb_get_converter (const GstCaps *from, const GstCaps *to);
#if 0
GstColorspaceConverter* gst_colorspace_yuv2rgb_get_converter (const GstCaps *from, const GstCaps *to);
#define gst_colorspace_convert(converter, src, dest) \
(converter)->convert((converter), (src), (dest))
void gst_colorspace_converter_destroy (GstColorSpaceConverter *space);
void gst_colorspace_converter_destroy (GstColorspaceConverter *space);
#endif
G_END_DECLS
#endif