Added MMX optimized yuv2rgb (AlienSong now plays back at only 6% CPU)

Original commit message from CVS:
Added MMX optimized yuv2rgb (AlienSong now plays back at only 6% CPU)
Added mpeg1 picture skipping and fixed a buffer overflow.
Added a system clock. The audiosink can now adjust the clock.
Fixed incorrect behaviour on 8, 15, 16, 24 and 32 bits displays.
Cleanup of the videosink, it now uses the color conversion library when
needed.
This commit is contained in:
Wim Taymans 2000-04-09 21:36:56 +00:00
parent 82cdfe8ba3
commit 5b0ba06f28
16 changed files with 809 additions and 177 deletions

View file

@ -13,6 +13,7 @@ libgst_la_SOURCES = \
$(GSTOBJECT_SRCS) \
gstpad.c \
gstbuffer.c \
gstclock.c \
gstelement.c \
gstelementfactory.c \
gstbin.c \
@ -38,6 +39,7 @@ libgstinclude_HEADERS = \
$(GSTOBJECT_INCLUDES) \
gstpad.h \
gstbuffer.h \
gstclock.h \
gstelement.h \
gstbin.h \
gstpipeline.h \

View file

@ -142,7 +142,7 @@ static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
switch(id) {
case ARG_LOCATION:
/* the element must be stopped in order to do this */
g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN));
if (src->filename) g_free(src->filename);
/* clear the filename if we get a NULL (is that possible?) */
@ -215,12 +215,13 @@ void gst_asyncdisksrc_push(GstSrc *src) {
/* create the buffer */
// FIXME: should eventually use a bufferpool for this
buf = GST_BUFFER(gst_buffer_new());
buf = gst_buffer_new();
g_return_if_fail(buf != NULL);
/* simply set the buffer to point to the correct region of the file */
GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset;
GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) >
asyncdisksrc->size) {
@ -230,6 +231,8 @@ void gst_asyncdisksrc_push(GstSrc *src) {
GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read;
asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf);
//gst_buffer_ref(buf);
/* we're done, push the buffer off now */
gst_pad_push(asyncdisksrc->srcpad,buf);
}
@ -265,6 +268,7 @@ void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) {
/* simply set the buffer to point to the correct region of the file */
GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset;
GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
if ((offset + size) > asyncdisksrc->size) {
GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset;
@ -293,6 +297,7 @@ static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) {
lseek(src->fd,0,SEEK_SET);
/* map the file into memory */
src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0);
madvise(src->map,src->size,2);
/* collapse state if that failed */
if (src->map == NULL) {
close(src->fd);

View file

@ -126,12 +126,16 @@ static void gst_audiosink_init(GstAudioSink *audiosink) {
gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain);
audiosink->fd = -1;
audiosink->clock = gst_clock_get_system();
gst_clock_register(audiosink->clock, GST_OBJECT(audiosink));
audiosink->clocktime = 0LL;
gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
}
void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
audio_buf_info ospace;
int frag;
g_return_if_fail(audiosink != NULL);
g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
@ -142,12 +146,15 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format);
ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels);
ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency);
ioctl(audiosink->fd,SNDCTL_DSP_GETBLKSIZE, &frag);
ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace);
g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n",
g_print("audiosink: setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
audiosink->frequency,audiosink->format,
(audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes);
(audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes, frag);
}
GstElement *gst_audiosink_new(gchar *name) {
@ -159,6 +166,7 @@ GstElement *gst_audiosink_new(gchar *name) {
void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
GstAudioSink *audiosink;
MetaAudioRaw *meta;
count_info info;
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
@ -179,7 +187,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
audiosink->channels = meta->channels;
audiosink->frequency = meta->frequency;
gst_audiosink_sync_parms(audiosink);
g_print("sound device set to format %d, %d channels, %dHz\n",
g_print("audiosink: sound device set to format %d, %d channels, %dHz\n",
audiosink->format,audiosink->channels,audiosink->frequency);
}
}
@ -189,10 +197,19 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
if (GST_BUFFER_DATA(buf) != NULL) {
gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
//g_print("audiosink: writing to soundcard\n");
if (audiosink->fd > 2)
if (audiosink->fd > 2) {
if (audiosink->clocktime == 0LL)
gst_clock_wait(audiosink->clock, audiosink->clocktime, GST_OBJECT(audiosink));
ioctl(audiosink->fd,SNDCTL_DSP_GETOPTR,&info);
audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
//g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
gst_clock_set(audiosink->clock, audiosink->clocktime);
write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
// (audiosink->format/8)*(audiosink->frequency)));
//g_print("audiosink: writing to soundcard ok\n");
}
}
//g_print("a unref\n");
gst_buffer_unref(buf);
@ -229,7 +246,7 @@ void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
g_return_val_if_fail(sink->fd == -1, FALSE);
g_print("attempting to open sound device\n");
g_print("audiosink: attempting to open sound device\n");
/* first try to open the sound card */
sink->fd = open("/dev/dsp",O_RDWR);
@ -241,7 +258,16 @@ static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
sink->channels = 2; /* stereo */
sink->frequency = 44100;
gst_audiosink_sync_parms(sink);
g_print("opened audio\n");
ioctl(sink->fd,SNDCTL_DSP_GETCAPS,&sink->caps);
g_print("audiosink: Capabilities\n");
if (sink->caps & DSP_CAP_DUPLEX) g_print("audiosink: Full duplex\n");
if (sink->caps & DSP_CAP_REALTIME) g_print("audiosink: Realtime\n");
if (sink->caps & DSP_CAP_BATCH) g_print("audiosink: Batch\n");
if (sink->caps & DSP_CAP_COPROC) g_print("audiosink: Has coprocessor\n");
if (sink->caps & DSP_CAP_TRIGGER) g_print("audiosink: Trigger\n");
if (sink->caps & DSP_CAP_MMAP) g_print("audiosink: Direct access\n");
g_print("audiosink: opened audio\n");
return TRUE;
}
@ -253,7 +279,7 @@ static void gst_audiosink_close_audio(GstAudioSink *sink) {
close(sink->fd);
sink->fd = -1;
g_print("closed sound device\n");
g_print("audiosink: closed sound device\n");
}
static gboolean gst_audiosink_start(GstElement *element,

View file

@ -24,6 +24,7 @@
#include <config.h>
#include <gst/gst.h>
#include <gst/gstclock.h>
#ifdef __cplusplus
@ -53,8 +54,11 @@ struct _GstAudioSink {
GstPad *sinkpad;
GstClockTime clocktime;
GstClock *clock;
/* soundcard state */
int fd;
int caps; /* the capabilities */
gint format;
gint channels;
gint frequency;

View file

@ -87,7 +87,7 @@ static void gst_queue_class_init(GstQueueClass *klass) {
gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT,
GTK_ARG_READABLE, ARG_LEVEL);
gtk_object_add_arg_type("GstQueue::max_level", GTK_TYPE_INT,
GTK_ARG_READWRITE, ARG_LEVEL);
GTK_ARG_READWRITE, ARG_MAX_LEVEL);
gstconnection_class->push = gst_queue_push;

View file

@ -11,5 +11,5 @@ noinst_HEADERS = yuv2rgb.h
CFLAGS += -Wall -O2 -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir)
INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include
LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_srcdir)/gst/libgst.la

View file

@ -58,8 +58,6 @@ GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstC
//return gst_colorspace_yuv2yuv_get_converter(srcspace, destspace);
}
}
else {
return NULL;
}
g_print("gst_colorspace: conversion not implemented\n");
return NULL;
}

View file

@ -21,7 +21,7 @@
#ifndef __GST_COLORSPACE_H__
#define __GST_COLORSPACE_H__
#include <gdk/gdk.h>
#include <gst/gstbuffer.h>
#include <gst/gstplugin.h>
@ -35,7 +35,8 @@ typedef enum {
GST_COLORSPACE_RGB24, // RGB
GST_COLORSPACE_BGR24, // RGB
GST_COLORSPACE_RGB32,
#define GST_COLORSPACE_RGB_LAST GST_COLORSPACE_RGB32
GST_COLORSPACE_BGR32,
#define GST_COLORSPACE_RGB_LAST GST_COLORSPACE_BGR32
#define GST_COLORSPACE_YUV_FIRST GST_COLORSPACE_YUV420
GST_COLORSPACE_YUV420, // YUV
@ -52,6 +53,7 @@ struct _GstColorSpaceParameters {
guint width;
guint height;
gchar *outbuf;
GdkVisual *visual;
};

View file

@ -23,11 +23,14 @@
#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);
GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
switch(src) {
case GST_COLORSPACE_RGB24:
switch(dest) {
case GST_COLORSPACE_RGB24:
return gst_colorspace_rgb_to_rgb_identity;
case GST_COLORSPACE_BGR24:
return gst_colorspace_rgb24_to_bgr24;
default:
@ -38,6 +41,8 @@ GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, G
switch(dest) {
case GST_COLORSPACE_RGB24:
return gst_colorspace_rgb24_to_bgr24;
case GST_COLORSPACE_BGR24:
return gst_colorspace_rgb_to_rgb_identity;
default:
break;
}
@ -45,9 +50,14 @@ GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, G
default:
break;
}
g_print("gst_colorspace: conversion not supported\n");
return NULL;
}
static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params) {
return src;
}
static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
gint size;
gchar temp;
@ -55,9 +65,16 @@ static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpacePar
DEBUG("gst_colorspace_rgb24_to_bgr24 %d\n", GST_BUFFER_SIZE(src));
data = GST_BUFFER_DATA(src);
size = GST_BUFFER_SIZE(src)/3;
if (params != NULL && params->outbuf != NULL) {
data = params->outbuf;
DEBUG("gst_colorspace: to buffer %p\n", data);
}
else {
data = GST_BUFFER_DATA(src);
}
while (size--) {
temp = data[0];
data[0] = data[2];

View file

@ -17,6 +17,7 @@
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
@ -25,10 +26,19 @@
#include <gst/gst.h>
#include <gstcolorspace.h>
#ifdef HAVE_LIBMMX
#include "mmx.h"
#endif
#include "yuv2rgb.h"
static GstBuffer *gst_colorspace_yuv422P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params);
static GstBuffer *gst_colorspace_yuv422P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params);
static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
unsigned char *lum,
@ -36,20 +46,56 @@ static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
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,
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,
unsigned char *lum,
unsigned char *cr,
unsigned char *cb,
unsigned char *out,
int cols, int rows);
static 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
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\n");
DEBUG("gst_colorspace_yuv2rgb_get_converter %d\n", dest);
switch(src) {
case GST_COLORSPACE_YUV422P:
switch(dest) {
case GST_COLORSPACE_BGR32:
//return gst_colorspace_yuv422P_to_bgr32;
return gst_colorspace_yuv422P_to_bgr32_mmx;
case GST_COLORSPACE_RGB32:
return gst_colorspace_yuv422P_to_rgb32;
case GST_COLORSPACE_RGB24:
return gst_colorspace_yuv422P_to_rgb24;
case GST_COLORSPACE_BGR24:
return gst_colorspace_yuv422P_to_bgr24;
case GST_COLORSPACE_RGB555:
case GST_COLORSPACE_RGB565:
case GST_COLORSPACE_BGR555:
return gst_colorspace_yuv422P_to_rgb16;
case GST_COLORSPACE_BGR565:
return gst_colorspace_yuv422P_to_bgr16_mmx;
default:
break;
}
@ -57,30 +103,166 @@ GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace src, G
default:
break;
}
g_print("gst_colorspace_yuv2rgb not implemented\n");
return NULL;
}
static GstBuffer *gst_colorspace_yuv422P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params) {
DEBUG("gst_colorspace_yuv422P_to_rgb24\n");
return src;
}
static GstBuffer *gst_colorspace_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params) {
static GstBuffer *gst_colorspace_yuv422P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params) {
static GstColorSpaceYUVTables *color_tables = NULL;
DEBUG("gst_colorspace_yuv422P_to_rgb16\n");
int size;
GstBuffer *buf = NULL;
guchar *out;
DEBUG("gst_colorspace_yuv422P_to_bgr32\n");
g_return_val_if_fail(params != NULL, NULL);
if (color_tables == NULL) {
color_tables = gst_colorspace_init_yuv(16, 0xF800, 0x07E0, 0x001F);
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_yuv422P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params) {
static GstColorSpaceYUVTables *color_tables = NULL;
int size;
GstBuffer *buf = NULL;
guchar *out;
DEBUG("gst_colorspace_yuv422P_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;
}
static GstBuffer *gst_colorspace_yuv422P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
static GstColorSpaceYUVTables *color_tables = NULL;
int size;
GstBuffer *buf = NULL;
guchar *out;
DEBUG("gst_colorspace_yuv422P_to_bgr24\n");
g_return_val_if_fail(params != NULL, NULL);
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;
}
static GstBuffer *gst_colorspace_yuv422P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params) {
static GstColorSpaceYUVTables *color_tables = NULL;
int size;
GstBuffer *buf = NULL;
guchar *out;
DEBUG("gst_colorspace_yuv422P_to_rgb24\n");
g_return_val_if_fail(params != NULL, NULL);
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_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params) {
static GstColorSpaceYUVTables *color_tables = NULL;
int size;
DEBUG("gst_colorspace_yuv422P_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;
gst_colorspace_yuv_to_rgb16(color_tables,
GST_BUFFER_DATA(src), // Y component
GST_BUFFER_DATA(src)+params->width*params->height, // cr component
GST_BUFFER_DATA(src)+params->width*params->height+
(params->width*params->height)/4, // cb component
GST_BUFFER_DATA(src)+size, // cr component
GST_BUFFER_DATA(src)+size+(size>>2), // cb component
params->outbuf,
params->height,
params->width);
@ -88,6 +270,59 @@ static GstBuffer *gst_colorspace_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceP
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_yuv422P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
int size;
GstBuffer *buf = NULL;
guchar *out;
DEBUG("gst_colorspace_yuv422P_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;
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;
}
static GstBuffer *gst_colorspace_yuv422P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
int size;
DEBUG("gst_colorspace_yuv422P_to_bgr16_mmx \n");
g_return_val_if_fail(params != NULL, NULL);
size = params->width * params->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);
return src;
}
#endif
/*
* How many 1 bits are there in the longword.
@ -241,7 +476,7 @@ gst_colorspace_init_yuv(long depth, long red_mask, long green_mask, long blue_ma
* A similar optimisation for Alpha for 64 bit has been
* prepared for, but is not yet implemented.
*/
if(!(depth == 32)) {
if(!(depth == 32) && !(depth == 24)) {
r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
@ -311,90 +546,115 @@ gst_colorspace_yuv_to_rgb16(tables, lum, cr, cb, out, rows, cols)
unsigned char *lum2;
int x, y;
int cr_r;
int cr_g;
int cb_g;
int crb_g;
int cb_b;
int cols_2 = cols/2;
int cols_2 = cols>>1;
row1 = (unsigned short *)out;
row2 = row1 + cols_2 + cols_2;
lum2 = lum + cols_2 + cols_2;
row2 = row1 + cols;
lum2 = lum + cols;
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
int R, G, B;
for (y=rows>>1; y; y--) {
for (x=cols_2; x; x--) {
CR = *cr++;
CB = *cb++;
cr_r = tables->Cr_r_tab[CR];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = tables->Cr_r_tab[CR];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
}
#endif
*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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
*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.
*/
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (CR + *(cr + cols_2 - 1)) >> 1;
CB = (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = tables->Cr_r_tab[CR];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
}
#endif
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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
L = tables->L_tab[(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
*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 += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
row1 += cols_2 + cols_2;
row2 += cols_2 + cols_2;
lum = lum2;
row1 = row2;
lum2 += cols;
row2 += cols;
}
}
static void
gst_colorspace_yuv_to_rgb24(tables, lum, cr, cb, 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 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];
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;
}
}
@ -434,85 +694,365 @@ gst_colorspace_yuv_to_rgb32(tables, lum, cr, cb, out, rows, cols)
unsigned char *lum2;
int x, y;
int cr_r;
int cr_g;
int cb_g;
int crb_g;
int cb_b;
int cols_2 = cols / 2;
int cols_2 = cols>>1;
row1 = (unsigned int *)out;
row2 = row1 + cols_2 + cols_2;
lum2 = lum + cols_2 + cols_2;
for (y=0; y<rows; y+=2) {
for (x=0; x<cols_2; x++) {
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];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
#ifdef INTERPOLATE
if(x != cols_2 - 1) {
CR = (CR + *cr) >> 1;
CB = (CB + *cb) >> 1;
cr_r = tables->Cr_r_tab[CR];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
}
#endif
*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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
*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.
*/
#ifdef INTERPOLATE
if(y != rows - 2) {
CR = (CR + *(cr + cols_2 - 1)) >> 1;
CB = (CB + *(cb + cols_2 - 1)) >> 1;
cr_r = tables->Cr_r_tab[CR];
cr_g = tables->Cr_g_tab[CR];
cb_g = tables->Cb_g_tab[CB];
cb_b = tables->Cb_b_tab[CB];
}
#endif
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++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
L = tables->L_tab [(int) *lum2++];
R = L + cr_r;
G = L + cr_g + cb_g;
B = L + cb_b;
*row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
*row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
}
lum += cols_2 + cols_2;
lum2 += cols_2 + cols_2;
row1 += cols_2 + cols_2;
row2 += cols_2 + cols_2;
lum = lum2;
row1 = row2;
lum2 += cols;
row2 += cols;
}
}
#ifdef HAVE_LIBMMX
static mmx_t MMX_80w = (mmx_t)(long long)0x0080008000800080LL; //dd 00080 0080h, 000800080h
static mmx_t MMX_00FFw = (mmx_t)(long long)0x00ff00ff00ff00ffLL; //dd 000FF 00FFh, 000FF00FFh
static mmx_t MMX_FF00w = (mmx_t)(long long)0xff00ff00ff00ff00LL; //dd 000FF 00FFh, 000FF00FFh
static mmx_t MMX16_Vredcoeff = (mmx_t)(long long)0x0066006600660066LL; //dd 00066 0066h, 000660066h
static mmx_t MMX16_Ublucoeff = (mmx_t)(long long)0x0081008100810081LL; //dd 00081 0081h, 000810081h
static mmx_t MMX16_Ugrncoeff = (mmx_t)(long long)0xffe8ffe8ffe8ffe8LL; //dd 0FFE7 FFE7h, 0FFE7FFE7h
static mmx_t MMX16_Vgrncoeff = (mmx_t)(long long)0xffcdffcdffcdffcdLL; //dd 0FFCC FFCCh, 0FFCCFFCCh
static mmx_t MMX16_Ycoeff = (mmx_t)(long long)0x004a004a004a004aLL; //dd 0004A 004Ah, 0004A004Ah
static mmx_t MMX32_Vredcoeff = (mmx_t)(long long)0x0059005900590059LL;
static mmx_t MMX32_Ubluecoeff = (mmx_t)(long long)0x0072007200720072LL;
static mmx_t MMX32_Ugrncoeff = (mmx_t)(long long)0xffeaffeaffeaffeaLL;
static mmx_t MMX32_Vgrncoeff = (mmx_t)(long long)0xffd2ffd2ffd2ffd2LL;
static void
gst_colorspace_yuv_to_bgr16_mmx(tables, lum, cr, cb, out, rows, cols)
GstColorSpaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
{
unsigned short *row1 = (unsigned short* )out; // 32 bit target
int cols8 = cols>>3;
int y, x;
for (y=rows>>1; y; y--) {
for (x=cols8; x; x--) {
movd_m2r(*(mmx_t *)cb, mm0); // 4 Cb 0 0 0 0 u3 u2 u1 u0
pxor_r2r(mm7, mm7);
movd_m2r(*(mmx_t *)cr, mm1); // 4 Cr 0 0 0 0 v3 v2 v1 v0
punpcklbw_r2r(mm7, mm0); // 4 W cb 0 u3 0 u2 0 u1 0 u0
punpcklbw_r2r(mm7, mm1); // 4 W cr 0 v3 0 v2 0 v1 0 v0
psubw_m2r(MMX_80w, mm0);
psubw_m2r(MMX_80w, mm1);
movq_r2r(mm0, mm2); // Cb 0 u3 0 u2 0 u1 0 u0
movq_r2r(mm1, mm3); // Cr
pmullw_m2r(MMX16_Ugrncoeff, mm2); // Cb2green 0 R3 0 R2 0 R1 0 R0
movq_m2r(*(mmx_t *)lum, mm6); // L1 l7 L6 L5 L4 L3 L2 L1 L0
pmullw_m2r(MMX16_Ublucoeff, mm0); // Cb2blue
pand_m2r(MMX_00FFw, mm6); // L1 00 L6 00 L4 00 L2 00 L0
pmullw_m2r(MMX16_Vgrncoeff, mm3); // Cr2green
movq_m2r(*(mmx_t *)lum, mm7); // L2
pmullw_m2r(MMX16_Vredcoeff, mm1); // Cr2red
// "psubw MMX_10w, %%mm6\n"
psrlw_i2r(8, mm7); // L2 00 L7 00 L5 00 L3 00 L1
pmullw_m2r(MMX16_Ycoeff, mm6); // lum1
// "psubw MMX_10w, %%mm7\n" // L2
paddw_r2r(mm3, mm2); // Cb2green + Cr2green == green
pmullw_m2r(MMX16_Ycoeff, mm7); // lum2
movq_r2r(mm6, mm4); // lum1
paddw_r2r(mm0, mm6); // lum1 +blue 00 B6 00 B4 00 B2 00 B0
movq_r2r(mm4, mm5); // lum1
paddw_r2r(mm1, mm4); // lum1 +red 00 R6 00 R4 00 R2 00 R0
paddw_r2r(mm2, mm5); // lum1 +green 00 G6 00 G4 00 G2 00 G0
psraw_i2r(6, mm4); // R1 0 .. 64
movq_r2r(mm7, mm3); // lum2 00 L7 00 L5 00 L3 00 L1
psraw_i2r(6, mm5); // G1 - .. +
paddw_r2r(mm0, mm7); // Lum2 +blue 00 B7 00 B5 00 B3 00 B1
psraw_i2r(6, mm6); // B1 0 .. 64
packuswb_r2r(mm4, mm4); // R1 R1
packuswb_r2r(mm5, mm5); // G1 G1
packuswb_r2r(mm6, mm6); // B1 B1
punpcklbw_r2r(mm4, mm4);
punpcklbw_r2r(mm5, mm5);
pand_m2r(MMX16_redmask, mm4);
psllw_i2r(3, mm5); // GREEN 1
punpcklbw_r2r(mm6, mm6);
pand_m2r(MMX16_grnmask, mm5);
pand_m2r(MMX16_redmask, mm6);
por_r2r(mm5, mm4); //
psrlw_i2r(11, mm6); // BLUE 1
movq_r2r(mm3, mm5); // lum2
paddw_r2r(mm1, mm3); // lum2 +red 00 R7 00 R5 00 R3 00 R1
paddw_r2r(mm2, mm5); // lum2 +green 00 G7 00 G5 00 G3 00 G1
psraw_i2r(6, mm3); // R2
por_r2r(mm6, mm4); // MM4
psraw_i2r(6, mm5); // G2
movq_m2r(*(mmx_t *)(lum+cols), mm6); // L3 load lum2
psraw_i2r(6, mm7);
packuswb_r2r(mm3, mm3);
packuswb_r2r(mm5, mm5);
packuswb_r2r(mm7, mm7);
pand_m2r(MMX_00FFw, mm6); // L3
punpcklbw_r2r(mm3, mm3);
// "psubw MMX_10w, %%mm6\n" // L3
punpcklbw_r2r(mm5, mm5);
pmullw_m2r(MMX16_Ycoeff, mm6); // lum3
punpcklbw_r2r(mm7, mm7);
psllw_i2r(3, mm5); // GREEN 2
pand_m2r(MMX16_redmask, mm7);
pand_m2r(MMX16_redmask, mm3);
psrlw_i2r(11, mm7); // BLUE 2
pand_m2r(MMX16_grnmask, mm5);
por_r2r(mm7, mm3);
movq_m2r(*(mmx_t *)(lum+cols), mm7); // L4 load lum2
por_r2r(mm5, mm3); //
psrlw_i2r(8, mm7); // L4
movq_r2r(mm4, mm5);
// "psubw MMX_10w, %%mm7\n" // L4
punpcklwd_r2r(mm3, mm4);
pmullw_m2r(MMX16_Ycoeff, mm7); // lum4
punpckhwd_r2r(mm3, mm5);
movq_r2m(mm4, *(row1)); // write row1
movq_r2m(mm5, *(row1+4)); // write row1
movq_r2r(mm6, mm4); // Lum3
paddw_r2r(mm0, mm6); // Lum3 +blue
movq_r2r(mm4, mm5); // Lum3
paddw_r2r(mm1, mm4); // Lum3 +red
paddw_r2r(mm2, mm5); // Lum3 +green
psraw_i2r(6, mm4);
movq_r2r(mm7, mm3); // Lum4
psraw_i2r(6, mm5);
paddw_r2r(mm0, mm7); // Lum4 +blue
psraw_i2r(6, mm6); // Lum3 +blue
movq_r2r(mm3, mm0); // Lum4
packuswb_r2r(mm4, mm4);
paddw_r2r(mm1, mm3); // Lum4 +red
packuswb_r2r(mm5, mm5);
paddw_r2r(mm2, mm0); // Lum4 +green
packuswb_r2r(mm6, mm6);
punpcklbw_r2r(mm4, mm4);
punpcklbw_r2r(mm5, mm5);
punpcklbw_r2r(mm6, mm6);
psllw_i2r(3, mm5); // GREEN 3
pand_m2r(MMX16_redmask, mm4);
psraw_i2r(6, mm3); // psr 6
psraw_i2r(6, mm0);
pand_m2r(MMX16_redmask, mm6); // BLUE
pand_m2r(MMX16_grnmask, mm5);
psrlw_i2r(11, mm6); // BLUE 3
por_r2r(mm5, mm4);
psraw_i2r(6, mm7);
por_r2r(mm6, mm4);
packuswb_r2r(mm3, mm3);
packuswb_r2r(mm0, mm0);
packuswb_r2r(mm7, mm7);
punpcklbw_r2r(mm3, mm3);
punpcklbw_r2r(mm0, mm0);
punpcklbw_r2r(mm7, mm7);
pand_m2r(MMX16_redmask, mm3);
pand_m2r(MMX16_redmask, mm7); // BLUE
psllw_i2r(3, mm0); // GREEN 4
psrlw_i2r(11, mm7);
pand_m2r(MMX16_grnmask, mm0);
por_r2r(mm7, mm3);
por_r2r(mm0, mm3);
movq_r2r(mm4, mm5);
punpcklwd_r2r(mm3, mm4);
punpckhwd_r2r(mm3, mm5);
movq_r2m(mm4, *(row1+cols));
movq_r2m(mm5, *(row1+cols+4));
lum+=8;
cr+=4;
cb+=4;
row1 +=8;
}
lum += cols;
row1 += cols;
}
emms();
}
static void
gst_colorspace_yuv_to_bgr32_mmx(tables, lum, cr, cb, out, rows, cols)
GstColorSpaceYUVTables *tables;
unsigned char *lum;
unsigned char *cr;
unsigned char *cb;
unsigned char *out;
int cols, rows;
{
guint32 *row1 = (guint32 *)out; // 32 bit target
int cols4 = cols>>2;
int y, x;
for (y=rows>>1; y; y--) {
for (x=cols4; x; x--) {
// create Cr (result in mm1)
movd_m2r(*(mmx_t *)cr, mm1); // 0 0 0 0 v3 v2 v1 v0
pxor_r2r(mm7, mm7); // 00 00 00 00 00 00 00 00
movd_m2r(*(mmx_t *)lum, mm2); // 0 0 0 0 l3 l2 l1 l0
punpcklbw_r2r(mm7, mm1); // 0 v3 0 v2 00 v1 00 v0
punpckldq_r2r(mm1, mm1); // 00 v1 00 v0 00 v1 00 v0
psubw_m2r(MMX_80w, mm1); // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0
// create Cr_g (result in mm0)
movq_r2r(mm1, mm0); // r1 r1 r0 r0 r1 r1 r0 r0
pmullw_m2r(MMX32_Vgrncoeff, mm0); // red*-46dec=0.7136*64
pmullw_m2r(MMX32_Vredcoeff, mm1); // red*89dec=1.4013*64
psraw_i2r(6, mm0); // red=red/64
psraw_i2r(6, mm1); // red=red/64
// create L1 L2 (result in mm2,mm4)
// L2=lum+cols
movq_m2r(*(mmx_t *)(lum+cols),mm3); // 0 0 0 0 L3 L2 L1 L0
punpckldq_r2r(mm3, mm2); // L3 L2 L1 L0 l3 l2 l1 l0
movq_r2r(mm2, mm4); // L3 L2 L1 L0 l3 l2 l1 l0
pand_m2r(MMX_FF00w, mm2); // L3 0 L1 0 l3 0 l1 0
pand_m2r(MMX_00FFw, mm4); // 0 L2 0 L0 0 l2 0 l0
psrlw_i2r(8, mm2); // 0 L3 0 L1 0 l3 0 l1
// create R (result in mm6)
movq_r2r(mm2, mm5); // 0 L3 0 L1 0 l3 0 l1
movq_r2r(mm4, mm6); // 0 L2 0 L0 0 l2 0 l0
paddsw_r2r(mm1, mm5); // lum1+red:x R3 x R1 x r3 x r1
paddsw_r2r(mm1, mm6); // lum1+red:x R2 x R0 x r2 x r0
packuswb_r2r(mm5, mm5); // R3 R1 r3 r1 R3 R1 r3 r1
packuswb_r2r(mm6, mm6); // R2 R0 r2 r0 R2 R0 r2 r0
pxor_r2r(mm7, mm7); // 00 00 00 00 00 00 00 00
punpcklbw_r2r(mm5, mm6); // R3 R2 R1 R0 r3 r2 r1 r0
// create Cb (result in mm1)
movd_m2r(*(mmx_t *)cb, mm1); // 0 0 0 0 u3 u2 u1 u0
punpcklbw_r2r(mm7, mm1); // 0 u3 0 u2 00 u1 00 u0
punpckldq_r2r(mm1, mm1); // 00 u1 00 u0 00 u1 00 u0
psubw_m2r(MMX_80w, mm1); // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0
// create Cb_g (result in mm5)
movq_r2r(mm1, mm5); // u1 u1 u0 u0 u1 u1 u0 u0
pmullw_m2r(MMX32_Ugrncoeff, mm5); // blue*-109dec=1.7129*64
pmullw_m2r(MMX32_Ubluecoeff, mm1); // blue*114dec=1.78125*64
psraw_i2r(6, mm5); // blue=red/64
psraw_i2r(6, mm1); // blue=blue/64
// create G (result in mm7)
movq_r2r(mm2, mm3); // 0 L3 0 L1 0 l3 0 l1
movq_r2r(mm4, mm7); // 0 L2 0 L0 0 l2 0 l1
paddsw_r2r(mm5, mm3); // lum1+Cb_g:x G3t x G1t x g3t x g1t
paddsw_r2r(mm5, mm7); // lum1+Cb_g:x G2t x G0t x g2t x g0t
paddsw_r2r(mm0, mm3); // lum1+Cr_g:x G3 x G1 x g3 x g1
paddsw_r2r(mm0, mm7); // lum1+blue:x G2 x G0 x g2 x g0
packuswb_r2r(mm3, mm3); // G3 G1 g3 g1 G3 G1 g3 g1
packuswb_r2r(mm7, mm7); // G2 G0 g2 g0 G2 G0 g2 g0
punpcklbw_r2r(mm3, mm7); // G3 G2 G1 G0 g3 g2 g1 g0
// create B (result in mm5)
movq_r2r(mm2, mm3); // 0 L3 0 L1 0 l3 0 l1
movq_r2r(mm4, mm5); // 0 L2 0 L0 0 l2 0 l1
paddsw_r2r(mm1, mm3); // lum1+blue:x B3 x B1 x b3 x b1
paddsw_r2r(mm1, mm5); // lum1+blue:x B2 x B0 x b2 x b0
packuswb_r2r(mm3, mm3); // B3 B1 b3 b1 B3 B1 b3 b1
packuswb_r2r(mm5, mm5); // B2 B0 b2 b0 B2 B0 b2 b0
punpcklbw_r2r(mm3, mm5); // B3 B2 B1 B0 b3 b2 b1 b0
// fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
pxor_r2r(mm2, mm2); // 0 0 0 0 0 0 0 0
pxor_r2r(mm4, mm4); // 0 0 0 0 0 0 0 0
movq_r2r(mm6, mm1); // R3 R2 R1 R0 r3 r2 r1 r0
movq_r2r(mm5, mm3); // B3 B2 B1 B0 b3 b2 b1 b0
// process lower lum
punpcklbw_r2r(mm4, mm1); // 0 r3 0 r2 0 r1 0 r0
punpcklbw_r2r(mm4, mm3); // 0 b3 0 b2 0 b1 0 b0
movq_r2r(mm1, mm2); // 0 r3 0 r2 0 r1 0 r0
movq_r2r(mm3, mm0); // 0 b3 0 b2 0 b1 0 b0
punpcklwd_r2r(mm1, mm3); // 0 r1 0 b1 0 r0 0 b0
punpckhwd_r2r(mm2, mm0); // 0 r3 0 b3 0 r2 0 b2
pxor_r2r(mm2, mm2); // 0 0 0 0 0 0 0 0
movq_r2r(mm7, mm1); // G3 G2 G1 G0 g3 g2 g1 g0
punpcklbw_r2r(mm1, mm2); // g3 0 g2 0 g1 0 g0 0
punpcklwd_r2r(mm4, mm2); // 0 0 g1 0 0 0 g0 0
por_r2r(mm3, mm2); // 0 r1 g1 b1 0 r0 g0 b0
movq_r2m(mm2, *(mmx_t *)row1); // wrote out ! row1
pxor_r2r(mm2, mm2); // 0 0 0 0 0 0 0 0
punpcklbw_r2r(mm1, mm4); // g3 0 g2 0 g1 0 g0 0
punpckhwd_r2r(mm2, mm4); // 0 0 g3 0 0 0 g2 0
por_r2r(mm0, mm4); // 0 r3 g3 b3 0 r2 g2 b2
movq_r2m(mm4, *(mmx_t *)(row1+2)); // wrote out ! row1
// fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
// this can be done "destructive"
pxor_r2r(mm2, mm2); // 0 0 0 0 0 0 0 0
punpckhbw_r2r(mm2, mm6); // 0 R3 0 R2 0 R1 0 R0
punpckhbw_r2r(mm1, mm5); // G3 B3 G2 B2 G1 B1 G0 B0
movq_r2r(mm5, mm1); // G3 B3 G2 B2 G1 B1 G0 B0
punpcklwd_r2r(mm6, mm1); // 0 R1 G1 B1 0 R0 G0 B0
movq_r2m(mm1, *(mmx_t *)(row1+cols)); // wrote out ! row2
punpckhwd_r2r(mm6, mm5); // 0 R3 G3 B3 0 R2 G2 B2
movq_r2m(mm5, *(mmx_t *)(row1+cols+2)); // wrote out ! row2
lum+=4;
cr+=2;
cb+=2;
row1 +=4;
}
lum += cols;
row1 += cols;
}
emms();
}
#endif

View file

@ -142,7 +142,7 @@ static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
switch(id) {
case ARG_LOCATION:
/* the element must be stopped in order to do this */
g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN));
if (src->filename) g_free(src->filename);
/* clear the filename if we get a NULL (is that possible?) */
@ -215,12 +215,13 @@ void gst_asyncdisksrc_push(GstSrc *src) {
/* create the buffer */
// FIXME: should eventually use a bufferpool for this
buf = GST_BUFFER(gst_buffer_new());
buf = gst_buffer_new();
g_return_if_fail(buf != NULL);
/* simply set the buffer to point to the correct region of the file */
GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset;
GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) >
asyncdisksrc->size) {
@ -230,6 +231,8 @@ void gst_asyncdisksrc_push(GstSrc *src) {
GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read;
asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf);
//gst_buffer_ref(buf);
/* we're done, push the buffer off now */
gst_pad_push(asyncdisksrc->srcpad,buf);
}
@ -265,6 +268,7 @@ void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) {
/* simply set the buffer to point to the correct region of the file */
GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset;
GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
if ((offset + size) > asyncdisksrc->size) {
GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset;
@ -293,6 +297,7 @@ static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) {
lseek(src->fd,0,SEEK_SET);
/* map the file into memory */
src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0);
madvise(src->map,src->size,2);
/* collapse state if that failed */
if (src->map == NULL) {
close(src->fd);

View file

@ -126,12 +126,16 @@ static void gst_audiosink_init(GstAudioSink *audiosink) {
gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain);
audiosink->fd = -1;
audiosink->clock = gst_clock_get_system();
gst_clock_register(audiosink->clock, GST_OBJECT(audiosink));
audiosink->clocktime = 0LL;
gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
}
void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
audio_buf_info ospace;
int frag;
g_return_if_fail(audiosink != NULL);
g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
@ -142,12 +146,15 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format);
ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels);
ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency);
ioctl(audiosink->fd,SNDCTL_DSP_GETBLKSIZE, &frag);
ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace);
g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n",
g_print("audiosink: setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
audiosink->frequency,audiosink->format,
(audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes);
(audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes, frag);
}
GstElement *gst_audiosink_new(gchar *name) {
@ -159,6 +166,7 @@ GstElement *gst_audiosink_new(gchar *name) {
void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
GstAudioSink *audiosink;
MetaAudioRaw *meta;
count_info info;
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
@ -179,7 +187,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
audiosink->channels = meta->channels;
audiosink->frequency = meta->frequency;
gst_audiosink_sync_parms(audiosink);
g_print("sound device set to format %d, %d channels, %dHz\n",
g_print("audiosink: sound device set to format %d, %d channels, %dHz\n",
audiosink->format,audiosink->channels,audiosink->frequency);
}
}
@ -189,10 +197,19 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
if (GST_BUFFER_DATA(buf) != NULL) {
gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
//g_print("audiosink: writing to soundcard\n");
if (audiosink->fd > 2)
if (audiosink->fd > 2) {
if (audiosink->clocktime == 0LL)
gst_clock_wait(audiosink->clock, audiosink->clocktime, GST_OBJECT(audiosink));
ioctl(audiosink->fd,SNDCTL_DSP_GETOPTR,&info);
audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
//g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
gst_clock_set(audiosink->clock, audiosink->clocktime);
write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
//audiosink->clocktime += (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
// (audiosink->format/8)*(audiosink->frequency)));
//g_print("audiosink: writing to soundcard ok\n");
}
}
//g_print("a unref\n");
gst_buffer_unref(buf);
@ -229,7 +246,7 @@ void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
g_return_val_if_fail(sink->fd == -1, FALSE);
g_print("attempting to open sound device\n");
g_print("audiosink: attempting to open sound device\n");
/* first try to open the sound card */
sink->fd = open("/dev/dsp",O_RDWR);
@ -241,7 +258,16 @@ static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
sink->channels = 2; /* stereo */
sink->frequency = 44100;
gst_audiosink_sync_parms(sink);
g_print("opened audio\n");
ioctl(sink->fd,SNDCTL_DSP_GETCAPS,&sink->caps);
g_print("audiosink: Capabilities\n");
if (sink->caps & DSP_CAP_DUPLEX) g_print("audiosink: Full duplex\n");
if (sink->caps & DSP_CAP_REALTIME) g_print("audiosink: Realtime\n");
if (sink->caps & DSP_CAP_BATCH) g_print("audiosink: Batch\n");
if (sink->caps & DSP_CAP_COPROC) g_print("audiosink: Has coprocessor\n");
if (sink->caps & DSP_CAP_TRIGGER) g_print("audiosink: Trigger\n");
if (sink->caps & DSP_CAP_MMAP) g_print("audiosink: Direct access\n");
g_print("audiosink: opened audio\n");
return TRUE;
}
@ -253,7 +279,7 @@ static void gst_audiosink_close_audio(GstAudioSink *sink) {
close(sink->fd);
sink->fd = -1;
g_print("closed sound device\n");
g_print("audiosink: closed sound device\n");
}
static gboolean gst_audiosink_start(GstElement *element,

View file

@ -24,6 +24,7 @@
#include <config.h>
#include <gst/gst.h>
#include <gst/gstclock.h>
#ifdef __cplusplus
@ -53,8 +54,11 @@ struct _GstAudioSink {
GstPad *sinkpad;
GstClockTime clocktime;
GstClock *clock;
/* soundcard state */
int fd;
int caps; /* the capabilities */
gint format;
gint channels;
gint frequency;

View file

@ -87,7 +87,7 @@ static void gst_queue_class_init(GstQueueClass *klass) {
gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT,
GTK_ARG_READABLE, ARG_LEVEL);
gtk_object_add_arg_type("GstQueue::max_level", GTK_TYPE_INT,
GTK_ARG_READWRITE, ARG_LEVEL);
GTK_ARG_READWRITE, ARG_MAX_LEVEL);
gstconnection_class->push = gst_queue_push;

View file

@ -49,6 +49,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
// construct queue and connect everything in the main pipelie
audio_queue = gst_elementfactory_make("queue","audio_queue");
gtk_object_set(GTK_OBJECT(audio_queue),"max_level",30,NULL);
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_queue));
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_thread));
gst_pad_connect(pad,
@ -71,7 +72,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
// construct internal pipeline elements
parse_video = gst_elementfactory_make("mp1videoparse","parse_video");
g_return_if_fail(parse_video != NULL);
decode = gst_elementfactory_make("mpeg_play","decode_video");
decode_video = gst_elementfactory_make("mpeg_play","decode_video");
g_return_if_fail(decode_video != NULL);
show = gst_elementfactory_make("videosink","show");
g_return_if_fail(show != NULL);
@ -86,19 +87,20 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
video_thread = gst_thread_new("video_thread");
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));
gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(decode_video));
gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(show));
// set up pad connections
gst_element_add_ghost_pad(GST_ELEMENT(video_thread),
gst_element_get_pad(parse_video,"sink"));
gst_pad_connect(gst_element_get_pad(parse_video,"src"),
gst_element_get_pad(decode,"sink"));
gst_pad_connect(gst_element_get_pad(decode,"src"),
gst_element_get_pad(decode_video,"sink"));
gst_pad_connect(gst_element_get_pad(decode_video,"src"),
gst_element_get_pad(show,"sink"));
// construct queue and connect everything in the main pipeline
video_queue = gst_elementfactory_make("queue","video_queue");
gtk_object_set(GTK_OBJECT(video_queue),"max_level",30,NULL);
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_queue));
gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_thread));
gst_pad_connect(pad,
@ -130,6 +132,7 @@ int main(int argc,char *argv[]) {
pipeline = gst_pipeline_new("pipeline");
g_return_if_fail(pipeline != NULL);
//src = gst_elementfactory_make("asyncdisksrc","src");
src = gst_elementfactory_make("disksrc","src");
g_return_if_fail(src != NULL);
gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL);