removed lib directories (they are in libs/gst now)

Original commit message from CVS:
removed lib directories (they are in libs/gst now)
This commit is contained in:
Andy Wingo 2001-12-24 20:52:36 +00:00
parent 7ec6702121
commit 107feed0de
52 changed files with 0 additions and 9612 deletions

View file

@ -1,14 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstaudio.la
libgstaudio_la_SOURCES = gstaudio.c
libgstaudioincludedir = $(includedir)/gst/libs/gstaudio
libgstaudioinclude_HEADERS = gstaudio.h
libgstaudio_la_LIBADD = $(GST_LIBS)
libgstaudio_la_CFLAGS = $(GST_CFLAGS) -finline-functions -ffast-math
# FIXME is this needed?
## from merge, kept for reference
## libgstaudio_la_CFLAGS = -O2 $(FOMIT_FRAME_POINTER) -finline-functions -ffast-math $(GLIB_CFLAGS) $(XML_CFLAGS) $(GST_CFLAGS)

View file

@ -1,152 +0,0 @@
/* Gnome-Streamer
* 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 "gstaudio.h"
int
gst_audio_frame_byte_size (GstPad* pad)
{
/* calculate byte size of an audio frame
* this should be moved closer to the gstreamer core
* and be implemented for every mime type IMO
* returns 0 if there's an error, or the byte size if everything's ok
*/
int width = 0;
int channels = 0;
GstCaps *caps = NULL;
/* get caps of pad */
caps = GST_PAD_CAPS (pad);
if (caps == NULL)
/* ERROR: could not get caps of pad */
return 0;
width = gst_caps_get_int (caps, "width");
channels = gst_caps_get_int (caps, "channels");
return (width / 8) * channels;
}
long
gst_audio_frame_length (GstPad* pad, GstBuffer* buf)
/* calculate length of buffer in frames
* this should be moved closer to the gstreamer core
* and be implemented for every mime type IMO
* returns 0 if there's an error, or the number of frames if everything's ok
*/
{
int frame_byte_size = 0;
frame_byte_size = gst_audio_frame_byte_size (pad);
if (frame_byte_size == 0)
/* error */
return 0;
/* FIXME: this function assumes the buffer size to be a whole multiple
* of the frame byte size
*/
return GST_BUFFER_SIZE (buf) / frame_byte_size;
}
long
gst_audio_frame_rate (GstPad *pad)
/*
* calculate frame rate (based on caps of pad)
* returns 0 if failed, rate if success
*/
{
GstCaps *caps = NULL;
/* get caps of pad */
caps = GST_PAD_CAPS (pad);
if (caps == NULL)
/* ERROR: could not get caps of pad */
return 0;
else
return gst_caps_get_int (caps, "rate");
}
double
gst_audio_length (GstPad* pad, GstBuffer* buf)
{
/* calculate length in seconds
* of audio buffer buf
* based on capabilities of pad
*/
long bytes = 0;
int width = 0;
int channels = 0;
long rate = 0L;
double length;
GstCaps *caps = NULL;
/* get caps of pad */
caps = GST_PAD_CAPS (pad);
if (caps == NULL)
{
/* ERROR: could not get caps of pad */
length = 0.0;
}
else
{
bytes = GST_BUFFER_SIZE (buf);
width = gst_caps_get_int (caps, "width");
channels = gst_caps_get_int (caps, "channels");
rate = gst_caps_get_int (caps, "rate");
length = (bytes * 8.0) / (double) (rate * channels * width);
}
return length;
}
long
gst_audio_highest_sample_value (GstPad* pad)
/* calculate highest possible sample value
* based on capabilities of pad
*/
{
gboolean is_signed = FALSE;
gint width = 0;
GstCaps *caps = NULL;
caps = GST_PAD_CAPS (pad);
// FIXME : Please change this to a better warning method !
if (caps == NULL)
printf ("WARNING: gstaudio: could not get caps of pad !\n");
width = gst_caps_get_int (caps, "width");
is_signed = gst_caps_get_boolean (caps, "signed");
if (is_signed) --width;
/* example : 16 bit, signed : samples between -32768 and 32767 */
return ((long) (1 << width));
}
gboolean
gst_audio_is_buffer_framed (GstPad* pad, GstBuffer* buf)
/* check if the buffer size is a whole multiple of the frame size */
{
if (GST_BUFFER_SIZE (buf) % gst_audio_frame_byte_size (pad) == 0)
return TRUE;
else
return FALSE;
}

View file

@ -1,109 +0,0 @@
/* Gnome-Streamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Library <2001> Thomas Vander Stichele <thomas@apestaart.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gst/gst.h>
/* for people that are looking at this source: the purpose of these defines is
* to make GstCaps a bit easier, in that you don't have to know all of the
* properties that need to be defined. you can just use these macros. currently
* (8/01) the only plugins that use these are the passthrough, speed, volume,
* and [de]interleave plugins. so. these are for convenience only, and do not
* specify the 'limits' of gstreamer. you might also use these definitions as a
* base for making your own caps, if need be.
*
* for example, to make a source pad that can output mono streams of either
* float or int:
template = gst_padtemplate_new
("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_append(gst_caps_new ("sink_int", "audio/raw",
GST_AUDIO_INT_PAD_TEMPLATE_PROPS),
gst_caps_new ("sink_float", "audio/raw",
GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS)),
NULL);
srcpad = gst_pad_new_from_template(template,"src");
* Andy Wingo, 18 August 2001 */
#define GST_AUDIO_INT_PAD_TEMPLATE_PROPS \
gst_props_new (\
"format", GST_PROPS_STRING ("int"),\
"law", GST_PROPS_INT (0),\
"endianness", GST_PROPS_INT (G_BYTE_ORDER),\
"signed", GST_PROPS_LIST (\
GST_PROPS_BOOLEAN (TRUE),\
GST_PROPS_BOOLEAN(FALSE)\
),\
"width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\
"depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\
"rate", GST_PROPS_INT_RANGE (4000, 96000),\
"channels", GST_PROPS_INT_RANGE (1, G_MAXINT),\
NULL)
#define GST_AUDIO_INT_MONO_PAD_TEMPLATE_PROPS \
gst_props_new (\
"format", GST_PROPS_STRING ("int"),\
"law", GST_PROPS_INT (0),\
"endianness", GST_PROPS_INT (G_BYTE_ORDER),\
"signed", GST_PROPS_LIST (\
GST_PROPS_BOOLEAN (TRUE),\
GST_PROPS_BOOLEAN(FALSE)\
),\
"width", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\
"depth", GST_PROPS_LIST (GST_PROPS_INT(8), GST_PROPS_INT(16)),\
"rate", GST_PROPS_INT_RANGE (4000, 96000),\
"channels", GST_PROPS_INT (1),\
NULL)
#define GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS \
gst_props_new (\
"format", GST_PROPS_STRING ("float"),\
"layout", GST_PROPS_STRING ("gfloat"),\
"intercept", GST_PROPS_FLOAT (0.0),\
"slope", GST_PROPS_FLOAT (1.0),\
"rate", GST_PROPS_INT_RANGE (4000, 96000),\
"channels", GST_PROPS_INT (1),\
NULL)
/*
* this library defines and implements some helper functions for audio
* handling
*/
/* get byte size of audio frame (based on caps of pad */
int gst_audio_frame_byte_size (GstPad* pad);
/* get length in frames of buffer */
long gst_audio_frame_length (GstPad* pad, GstBuffer* buf);
/* get frame rate based on caps */
long gst_audio_frame_rate (GstPad *pad);
/* calculate length in seconds of audio buffer buf based on caps of pad */
double gst_audio_length (GstPad* pad, GstBuffer* buf);
/* calculate highest possible sample value based on capabilities of pad */
long gst_audio_highest_sample_value (GstPad* pad);
/* check if the buffer size is a whole multiple of the frame size */
gboolean gst_audio_is_buffer_framed (GstPad* pad, GstBuffer* buf);

View file

@ -1,22 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstcontrol.la
libgstcontrol_la_SOURCES = \
gstcontrol.c \
gstdparammanager.c \
gstdparam.c \
gstdplinearinterp.c
libgstcontrolincludedir = $(includedir)/gst/libs/control
libgstcontrolinclude_HEADERS = \
gstcontrol.h \
gstdparammanager.h \
gstdparam.h \
gstdparamcommon.h \
gstdplinearinterp.h
libgstcontrol_la_LIBADD = $(GST_LIBS)
libgstcontrol_la_CFLAGS = $(GST_CFLAGS) -finline-functions -ffast-math

View file

@ -1,27 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstcontrol.c: GStreamer control utility library
*
* 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 "gstcontrol.h"
void
gst_control_init (int *argc, char **argv[]) {
_gst_dpman_initialize ();
}

View file

@ -1,40 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstcontrol.h: GStreamer control utility library
*
* 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 __GST_CONTROL_H__
#define __GST_CONTROL_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <libs/control/gstdparammanager.h>
#include <libs/control/gstdparam.h>
#include <libs/control/gstdplinearinterp.h>
void gst_control_init (int *argc, char **argv[]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_CONTROL_H__ */

View file

@ -1,408 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdparam.c: Dynamic Parameter functionality
*
* 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 <math.h>
#include <string.h>
#include <gst/gstinfo.h>
#include "gstdparam.h"
#include "gstdparammanager.h"
static void gst_dparam_class_init (GstDParamClass *klass);
static void gst_dparam_init (GstDParam *dparam);
static void gst_dparam_dispose (GObject *object);
static void gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp);
static GValue** gst_dparam_get_point_realtime (GstDParam *dparam, gint64 timestamp);
GType
gst_dparam_get_type(void) {
static GType dparam_type = 0;
if (!dparam_type) {
static const GTypeInfo dparam_info = {
sizeof(GstDParamClass),
NULL,
NULL,
(GClassInitFunc)gst_dparam_class_init,
NULL,
NULL,
sizeof(GstDParam),
0,
(GInstanceInitFunc)gst_dparam_init,
};
dparam_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParam", &dparam_info, 0);
}
return dparam_type;
}
static void
gst_dparam_class_init (GstDParamClass *klass)
{
GObjectClass *gobject_class;
GstDParamClass *dparam_class;
GstObjectClass *gstobject_class;
gobject_class = (GObjectClass*)klass;
dparam_class = (GstDParamClass*)klass;
gstobject_class = (GstObjectClass*) klass;
gobject_class->dispose = gst_dparam_dispose;
//gstobject_class->save_thyself = gst_dparam_save_thyself;
}
static void
gst_dparam_init (GstDParam *dparam)
{
g_return_if_fail (dparam != NULL);
GST_DPARAM_VALUE(dparam) = NULL;
GST_DPARAM_TYPE(dparam) = 0;
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)=0LL;
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)=0LL;
GST_DPARAM_READY_FOR_UPDATE(dparam)=FALSE;
dparam->lock = g_mutex_new ();
}
/**
* gst_dparam_new:
* @type: the type that this dparam will store
*
* Returns: a new instance of GstDParam
*/
GstDParam*
gst_dparam_new (GType type)
{
GstDParam *dparam;
dparam = g_object_new (gst_dparam_get_type (), NULL);
dparam->do_update_func = gst_dparam_do_update_realtime;
dparam->get_point_func = gst_dparam_get_point_realtime;
dparam->point = gst_dparam_new_value_array(type, 0);
GST_DPARAM_TYPE(dparam) = type;
return dparam;
}
static void
gst_dparam_dispose (GObject *object)
{
GstDParam *dparam = GST_DPARAM(object);
GValue **point = dparam->point;
guint i = 0;
gchar *dparam_name = g_strdup(GST_DPARAM_NAME(dparam));
g_print("disposing of %s\n", dparam_name);
if (GST_DPARAM_MANAGER(dparam)){
gst_dpman_detach_dparam(GST_DPARAM_MANAGER(dparam), dparam_name);
}
point = dparam->point;
while (point[i]){
g_value_unset(point[i]);
g_free(point[i]);
i++;
}
g_free(dparam_name);
}
/**
* gst_dparam_attach
* @dparam: GstDParam instance
* @manager: the GstDParamManager that this dparam belongs to
*
*/
void
gst_dparam_attach (GstDParam *dparam, GstDParamManager *manager, GValue *value, GstDParamSpec *spec)
{
g_return_if_fail (dparam != NULL);
g_return_if_fail (GST_IS_DPARAM (dparam));
g_return_if_fail (manager != NULL);
g_return_if_fail (GST_IS_DPMAN (manager));
g_return_if_fail (value != NULL);
g_return_if_fail (spec != NULL);
g_return_if_fail (GST_DPARAM_TYPE(dparam) == G_VALUE_TYPE(value));
GST_DPARAM_NAME(dparam) = spec->dparam_name;
GST_DPARAM_VALUE(dparam) = value;
GST_DPARAM_SPEC(dparam) = spec;
GST_DPARAM_MANAGER(dparam) = manager;
}
/**
* gst_dparam_detach
* @dparam: GstDParam instance
* @manager: the GstDParamManager that this dparam belongs to
*
*/
void
gst_dparam_detach (GstDParam *dparam)
{
g_return_if_fail (dparam != NULL);
g_return_if_fail (GST_IS_DPARAM (dparam));
GST_DPARAM_NAME(dparam) = NULL;
GST_DPARAM_VALUE(dparam) = NULL;
GST_DPARAM_SPEC(dparam) = NULL;
GST_DPARAM_MANAGER(dparam) = NULL;
}
/**
* gst_dparam_new_value_array
* @type: the type of the first GValue in the array
* @...: the type of other GValues in the array
*
* The list of types should be terminated with a 0.
* If the type of a value is not yet known then use G_TYPE_NONE .
*
* Returns: an newly created array of GValues
*/
GValue**
gst_dparam_new_value_array(GType type, ...)
{
GValue **point;
GValue *value;
guint x;
guint values_length = 0;
va_list var_args;
GType each_type;
va_start (var_args, type);
each_type = type;
while (each_type){
values_length++;
each_type = va_arg (var_args, GType);
}
va_end (var_args);
point = g_new0(GValue*,values_length + 1);
va_start (var_args, type);
each_type = type;
for (x=0 ; x < values_length ; x++){
value = g_new0(GValue,1);
if (each_type != G_TYPE_NONE){
g_value_init(value, each_type);
}
point[x] = value;
each_type = va_arg (var_args, GType);
}
point[values_length] = NULL;
va_end (var_args);
GST_DEBUG(GST_CAT_PARAMS, "array with %d values created\n", values_length);
return point;
}
void
gst_dparam_set_value_from_string(GValue *value, const gchar *value_str)
{
g_return_if_fail(value != NULL);
g_return_if_fail(value_str != NULL);
GST_DEBUG(GST_CAT_PARAMS, "parsing '%s' to type %s\n", value_str, g_type_name(G_VALUE_TYPE(value)));
switch (G_VALUE_TYPE(value)) {
case G_TYPE_STRING:
g_value_set_string(value, g_strdup(value_str));
break;
case G_TYPE_ENUM:
case G_TYPE_INT: {
gint i;
sscanf (value_str, "%d", &i);
g_value_set_int(value, i);
break;
}
case G_TYPE_UINT: {
guint i;
sscanf (value_str, "%u", &i);
g_value_set_uint(value, i);
break;
}
case G_TYPE_LONG: {
glong i;
sscanf (value_str, "%ld", &i);
g_value_set_long(value, i);
break;
}
case G_TYPE_ULONG: {
gulong i;
sscanf (value_str, "%lu", &i);
g_value_set_ulong(value, i);
break;
}
case G_TYPE_BOOLEAN: {
gboolean i = FALSE;
if (!strncmp ("true", value_str, 4)) i = TRUE;
g_value_set_boolean(value, i);
break;
}
case G_TYPE_CHAR: {
gchar i;
sscanf (value_str, "%c", &i);
g_value_set_char(value, i);
break;
}
case G_TYPE_UCHAR: {
guchar i;
sscanf (value_str, "%c", &i);
g_value_set_uchar(value, i);
break;
}
case G_TYPE_FLOAT: {
gfloat i;
sscanf (value_str, "%f", &i);
g_value_set_float(value, i);
break;
}
case G_TYPE_DOUBLE: {
gfloat i;
sscanf (value_str, "%g", &i);
g_value_set_double(value, (gdouble)i);
break;
}
default:
break;
}
}
static void
gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp)
{
GST_DPARAM_LOCK(dparam);
GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE;
GST_DEBUG(GST_CAT_PARAMS, "updating value for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
g_value_copy(dparam->point[0], GST_DPARAM_VALUE(dparam));
GST_DPARAM_UNLOCK(dparam);
}
static GValue**
gst_dparam_get_point_realtime (GstDParam *dparam, gint64 timestamp)
{
GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
return dparam->point;
}
/**********************
* GstDParamSmooth
**********************/
static void gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp);
static GValue** gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp);
/**
* gst_dparam_smooth_new:
* @type: the type that this dparam will store
*
* Returns: a new instance of GstDParamSmooth
*/
GstDParam*
gst_dparam_smooth_new (GType type)
{
GstDParam *dparam;
dparam = g_object_new (gst_dparam_get_type (), NULL);
dparam->do_update_func = gst_dparam_do_update_smooth;
dparam->get_point_func = gst_dparam_get_point_smooth;
dparam->point = gst_dparam_new_value_array(type, type, G_TYPE_FLOAT, 0);
GST_DPARAM_TYPE(dparam) = type;
return dparam;
}
static void
gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp)
{
gint64 time_diff;
gfloat time_ratio;
time_diff = MIN(GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam),
timestamp - GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam));
time_ratio = (gfloat)time_diff / g_value_get_float(dparam->point[2]);
GST_DPARAM_LOCK(dparam);
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam);
while(GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp){
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) += GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam);
}
GST_DEBUG(GST_CAT_PARAMS, "last:%lld current:%lld next:%lld\n",
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam), timestamp, GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam));
switch (G_VALUE_TYPE(GST_DPARAM_VALUE(dparam))){
case G_TYPE_FLOAT: {
gfloat current, target, max_change, current_diff, final_val;
target = g_value_get_float(dparam->point[0]);
current = g_value_get_float(GST_DPARAM_VALUE(dparam));
max_change = time_ratio * g_value_get_float(dparam->point[1]);
GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f max_change:%f \n",
target, current, max_change);
if (dparam->spec->is_log){
gfloat current_log;
current_log = log(current);
current_diff = ABS(current_log - log(target));
if (current_diff > max_change)
final_val = (target < current) ? exp(current_log-max_change) : exp(current_log+max_change);
else
final_val = target;
}
else {
current_diff = ABS (current - target);
if (current_diff > max_change)
final_val = (target < current) ? current-max_change : current+max_change;
else
final_val = target;
}
GST_DPARAM_READY_FOR_UPDATE(dparam) = (current_diff > max_change);
g_value_set_float(GST_DPARAM_VALUE(dparam), final_val);
break;
}
default:
break;
}
//GST_DEBUG(GST_CAT_PARAMS, "smooth update for %s(%p): %f\n",
// GST_DPARAM_NAME (dparam),dparam, g_value_get_float(GST_DPARAM_VALUE(dparam)));
GST_DPARAM_UNLOCK(dparam);
}
static GValue**
gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp)
{
GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam);
return dparam->point;
}

View file

@ -1,147 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdparam.h: Dynamic Parameter functionality
*
* 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 __GST_DPARAM_H__
#define __GST_DPARAM_H__
#include <gst/gstobject.h>
#include <gst/gstprops.h>
#include <libs/control/gstdparamcommon.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_DPARAM (gst_dparam_get_type ())
#define GST_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPARAM,GstDParam))
#define GST_DPARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPARAM,GstDParam))
#define GST_IS_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPARAM))
#define GST_IS_DPARAM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPARAM))
#define GST_DPARAM_NAME(dparam) (GST_OBJECT_NAME(dparam))
#define GST_DPARAM_PARENT(dparam) (GST_OBJECT_PARENT(dparam))
#define GST_DPARAM_VALUE(dparam) ((dparam)->value)
#define GST_DPARAM_SPEC(dparam) ((dparam)->spec)
#define GST_DPARAM_MANAGER(dparam) ((dparam)->manager)
#define GST_DPARAM_TYPE(dparam) ((dparam)->type)
#define GST_DPARAM_LOCK(dparam) (g_mutex_lock((dparam)->lock))
#define GST_DPARAM_UNLOCK(dparam) (g_mutex_unlock((dparam)->lock))
#define GST_DPARAM_READY_FOR_UPDATE(dparam) ((dparam)->ready_for_update)
#define GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam) ((dparam)->default_update_period)
#define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) ((dparam)->next_update_timestamp)
#define GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) ((dparam)->last_update_timestamp)
#define GST_DPARAM_GET_POINT(dparam, timestamp) \
((dparam->get_point_func)(dparam, timestamp))
#define GST_DPARAM_FIND_POINT(dparam, timestamp, search_flag) \
((dparam->find_point_func)(dparam, data, search_flag))
#define GST_DPARAM_DO_UPDATE(dparam, timestamp) \
((dparam->do_update_func)(dparam, timestamp))
#define GST_DPARAM_INSERT_POINT(dparam, timestamp) \
((dparam->insert_point_func)(dparam, timestamp))
#define GST_DPARAM_REMOVE_POINT(dparam, data) \
((dparam->remove_point_func)(dparam, data))
typedef enum {
GST_DPARAM_CLOSEST,
GST_DPARAM_CLOSEST_AFTER,
GST_DPARAM_CLOSEST_BEFORE,
GST_DPARAM_EXACT,
} GstDParamSearchFlag;
typedef enum {
GST_DPARAM_NOT_FOUND = 0,
GST_DPARAM_FOUND_EXACT,
GST_DPARAM_FOUND_CLOSEST,
} GstDParamSearchResult;
typedef struct _GstDParamClass GstDParamClass;
typedef GValue** (*GstDParamInsertPointFunction) (GstDParam *dparam, guint64 timestamp);
typedef void (*GstDParamRemovePointFunction) (GstDParam *dparam, GValue** point);
typedef GValue** (*GstDParamGetPointFunction) (GstDParam *dparam, gint64 timestamp);
typedef GstDParamSearchResult (*GstDParamFindPointFunction) (GstDParam *dparam, gint64 *timestamp, GstDParamSearchFlag search_flag);
typedef void (*GstDParamDoUpdateFunction) (GstDParam *dparam, gint64 timestamp);
struct _GstDParam {
GstObject object;
GstDParamGetPointFunction get_point_func;
GstDParamFindPointFunction find_point_func;
GstDParamDoUpdateFunction do_update_func;
GstDParamInsertPointFunction insert_point_func;
GstDParamRemovePointFunction remove_point_func;
GMutex *lock;
GValue *value;
GstDParamManager *manager;
GstDParamSpec *spec;
GValue **point;
GType type;
gint64 last_update_timestamp;
gint64 next_update_timestamp;
gint64 default_update_period;
gboolean ready_for_update;
};
struct _GstDParamClass {
GstObjectClass parent_class;
/* signal callbacks */
};
struct _GstDParamSpec {
gchar *dparam_name;
gchar *unit_name;
GValue *min_val;
GValue *max_val;
GValue *default_val;
gboolean is_log;
gboolean is_rate;
};
GType gst_dparam_get_type (void);
GstDParam* gst_dparam_new (GType type);
void gst_dparam_attach (GstDParam *dparam, GstDParamManager *manager, GValue *value, GstDParamSpec *spec);
void gst_dparam_detach (GstDParam *dparam);
GValue** gst_dparam_new_value_array(GType type, ...);
void gst_dparam_set_value_from_string(GValue *value, const gchar *value_str);
/**********************
* GstDParamSmooth
**********************/
GstDParam* gst_dparam_smooth_new (GType type);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_DPARAM_H__ */

View file

@ -1,37 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdparamcommon.h: Dynamic Parameter common header
*
* 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 __GST_DPCOMMON_H__
#define __GST_DPCOMMON_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _GstDParam GstDParam;
typedef struct _GstDParamSpec GstDParamSpec;
typedef struct _GstDParamManager GstDParamManager;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_DPCOMMON_H__ */

View file

@ -1,782 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdparammanager.c: Dynamic Parameter group functionality
*
* 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 "gstdparammanager.h"
#include <gst/gstelement.h>
#include <gst/gstinfo.h>
static GHashTable *_element_registry;
static void gst_dpman_class_init (GstDParamManagerClass *klass);
static void gst_dpman_init (GstDParamManager *dpman);
static void gst_dpman_dispose (GObject *object);
static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method);
static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name);
static void gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman);
static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman);
static guint gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp);
static guint gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp);
static guint gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count);
static GObjectClass *parent_class;
void
_gst_dpman_initialize()
{
}
GType
gst_dpman_get_type (void)
{
static GType dpman_type = 0;
if (!dpman_type) {
static const GTypeInfo dpman_info = {
sizeof(GstDParamManagerClass),
NULL,
NULL,
(GClassInitFunc)gst_dpman_class_init,
NULL,
NULL,
sizeof(GstDParamManager),
0,
(GInstanceInitFunc)gst_dpman_init,
};
dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParamManager", &dpman_info, 0);
}
return dpman_type;
}
static void
gst_dpman_class_init (GstDParamManagerClass *klass)
{
GstObjectClass *gstobject_class;
GObjectClass *gobject_class;
parent_class = g_type_class_peek_parent (klass);
gstobject_class = (GstObjectClass*) klass;
gobject_class = (GObjectClass*) klass;
gobject_class->dispose = gst_dpman_dispose;
klass->modes = g_hash_table_new(g_str_hash,g_str_equal);
gst_dpman_register_mode (klass, "synchronous",
gst_dpman_preprocess_synchronous, gst_dpman_process_noop, NULL, NULL);
gst_dpman_register_mode (klass, "asynchronous",
gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL);
gst_dpman_register_mode (klass, "disabled",
gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL);
_element_registry = g_hash_table_new(NULL,NULL);
}
static void
gst_dpman_init (GstDParamManager *dpman)
{
GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal);
GST_DPMAN_DPARAMS_LIST(dpman) = NULL;
GST_DPMAN_NAME(dpman) = NULL;
GST_DPMAN_PARENT(dpman) = NULL;
GST_DPMAN_MODE_NAME(dpman) = NULL;
GST_DPMAN_MODE(dpman) = NULL;
GST_DPMAN_MODE_DATA(dpman) = NULL;
GST_DPMAN_RATE(dpman) = 0;
}
/**
* gst_dpman_new:
* @name: name of the GstDParamManager instance
* @parent: element which created this instance
*
* Returns: a new instance of GstDParamManager
*/
GstDParamManager*
gst_dpman_new (gchar *name, GstElement *parent)
{
GstDParamManager *dpman;
g_return_val_if_fail (name != NULL, NULL);
dpman = g_object_new (gst_dpman_get_type (), NULL);
gst_object_set_name (GST_OBJECT (dpman), name);
gst_dpman_set_parent(dpman, parent);
gst_dpman_set_mode(dpman, "disabled");
return dpman;
}
static void
gst_dpman_dispose (GObject *object)
{
/* GstDParamManager *dpman = GST_DPMAN(object); */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
/**
* gst_dpman_add_required_dparam_callback:
* @dpman: GstDParamManager instance
* @dparam_name: a parameter name unique to this GstDParamManager
* @type: the GValue type that this parameter will store
* @update_func: callback to update the element with the new value
* @update_data: will be included in the call to update_func
*
* Returns: true if it was successfully added
*/
gboolean
gst_dpman_add_required_dparam_callback (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
GstDPMUpdateFunction update_func,
gpointer update_data)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
g_return_val_if_fail (update_func != NULL, FALSE);
dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_CALLBACK);
g_return_val_if_fail (dpwrap != NULL, FALSE);
GST_DEBUG(GST_CAT_PARAMS,"adding required callback dparam '%s' of type %s\n", dparam_name, g_type_name(type));
dpwrap->update_func = update_func;
dpwrap->update_data = update_data;
return TRUE;
}
/**
* gst_dpman_add_required_dparam_direct:
* @dpman: GstDParamManager instance
* @dparam_name: a parameter name unique to this GstDParamManager
* @type: the GValue type that this parameter will store
* @update_data: pointer to the member to be updated
*
* Returns: true if it was successfully added
*/
gboolean
gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
gpointer update_data)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
g_return_val_if_fail (update_data != NULL, FALSE);
dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_DIRECT);
g_return_val_if_fail (dpwrap != NULL, FALSE);
GST_DEBUG(GST_CAT_PARAMS,"adding required direct dparam '%s' of type %s\n", dparam_name, g_type_name(type));
dpwrap->update_data = update_data;
return TRUE;
}
/**
* gst_dpman_add_required_dparam_array:
* @dpman: GstDParamManager instance
* @dparam_name: a parameter name unique to this GstDParamManager
* @type: the GValue type that this parameter will store
* @update_data: pointer to where the array will be stored
*
* Returns: true if it was successfully added
*/
gboolean
gst_dpman_add_required_dparam_array (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
gpointer update_data)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
g_return_val_if_fail (update_data != NULL, FALSE);
dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_ARRAY);
g_return_val_if_fail (dpwrap != NULL, FALSE);
GST_DEBUG(GST_CAT_PARAMS,"adding required array dparam '%s' of type %s\n", dparam_name, g_type_name(type));
dpwrap->update_data = update_data;
return TRUE;
}
/**
* gst_dpman_remove_required_dparam:
* @dpman: GstDParamManager instance
* @dparam_name: the name of an existing parameter
*
*/
void
gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name)
{
GstDParamWrapper* dpwrap;
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
g_return_if_fail (dparam_name != NULL);
dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
g_return_if_fail(dpwrap != NULL);
g_return_if_fail(dpwrap->dparam == NULL);
GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s\n", dparam_name);
g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name);
GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
g_free(dpwrap->value);
g_free(dpwrap);
}
/**
* gst_dpman_attach_dparam:
* @dpman: GstDParamManager instance
* @dparam_name: a name previously added with gst_dpman_add_required_dparam
* @dparam: GstDParam instance to attach
*
* Returns: true if it was successfully attached
*/
gboolean
gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
g_return_val_if_fail (dparam_name != NULL, FALSE);
g_return_val_if_fail (dparam != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE);
g_return_val_if_fail (dparam != NULL, FALSE);
dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
g_return_val_if_fail(dpwrap != NULL, FALSE);
g_return_val_if_fail(dpwrap->value != NULL, FALSE);
dpwrap->dparam = dparam;
gst_dparam_attach(dparam, dpman, dpwrap->value, dpwrap->spec);
return TRUE;
}
/**
* gst_dpman_detach_dparam:
* @dpman: GstDParamManager instance
* @dparam_name: the name of a parameter with a previously attached GstDParam
*
*/
void
gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name)
{
GstDParamWrapper* dpwrap;
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
g_return_if_fail (dparam_name != NULL);
dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
g_return_if_fail(dpwrap);
gst_dparam_detach(dpwrap->dparam);
dpwrap->dparam = NULL;
}
/**
* gst_dpman_get_dparam:
* @dpman: GstDParamManager instance
* @name: the name of an existing dparam instance
*
* Returns: the dparam with the given name - or NULL otherwise
*/
GstDParam *
gst_dpman_get_dparam (GstDParamManager *dpman, gchar *name)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, NULL);
g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
g_return_val_if_fail (name != NULL, NULL);
dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
g_return_val_if_fail (dpwrap != NULL, NULL);
return dpwrap->dparam;
}
/**
* gst_dpman_get_dparam_type:
* @dpman: GstDParamManager instance
* @name: the name of dparam
*
* Returns: the type that this dparam requires/uses
*/
GType
gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, 0);
g_return_val_if_fail (GST_IS_DPMAN (dpman), 0);
g_return_val_if_fail (name != NULL, 0);
dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name);
g_return_val_if_fail (dpwrap != NULL, 0);
return G_VALUE_TYPE(dpwrap->value);
}
GstDParamSpec**
gst_dpman_list_dparam_specs(GstDParamManager *dpman)
{
GstDParamWrapper* dpwrap;
GSList *dpwraps;
GstDParamSpec** dparam_specs;
guint x = 0;
g_return_val_if_fail (dpman != NULL, NULL);
g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
dpwraps = GST_DPMAN_DPARAMS_LIST(dpman);
dparam_specs = g_new0(GstDParamSpec*, g_slist_length(dpwraps) + 1);
while (dpwraps){
dpwrap = (GstDParamWrapper*)dpwraps->data;
dparam_specs[x++] = dpwrap->spec;
dpwraps = g_slist_next(dpwraps);
}
return dparam_specs;
}
GstDParamSpec*
gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, NULL);
g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
g_return_val_if_fail (dparam_name != NULL, NULL);
dpwrap = gst_dpman_get_wrapper(dpman, dparam_name);
return dpwrap->spec;
}
void
gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name)
{
}
/**
* gst_dpman_register_mode
* @klass: GstDParamManagerClass class instance
* @modename: the unique name of the new mode
* @preprocessfunc: the function which will be called before each buffer is processed
* @processfunc: the function which may be called throughout the processing of a buffer
* @setupfunc: the function which initialises the mode when activated
* @teardownfunc: the function which frees any resources the mode uses
*
*/
void
gst_dpman_register_mode (GstDParamManagerClass *klass,
gchar *modename,
GstDPMModePreProcessFunction preprocessfunc,
GstDPMModeProcessFunction processfunc,
GstDPMModeSetupFunction setupfunc,
GstDPMModeTeardownFunction teardownfunc)
{
GstDPMMode *mode;
g_return_if_fail (klass != NULL);
g_return_if_fail (modename != NULL);
g_return_if_fail (GST_IS_DPMAN_CLASS (klass));
mode = g_new0(GstDPMMode,1);
mode->preprocessfunc = preprocessfunc;
mode->processfunc = processfunc;
mode->setupfunc = setupfunc;
mode->teardownfunc = teardownfunc;
g_hash_table_insert(klass->modes, modename, mode);
GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered\n", modename);
}
/**
* gst_dpman_set_mode
* @dpman: GstDParamManager instance
* @modename: the name of the mode to use
*
* Returns: TRUE if the mode was set, FALSE otherwise
*/
gboolean
gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename)
{
GstDPMMode *mode=NULL;
GstDParamManagerClass *oclass;
g_return_val_if_fail (dpman != NULL, FALSE);
g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE);
g_return_val_if_fail (modename != NULL, FALSE);
oclass = (GstDParamManagerClass*)(G_OBJECT_GET_CLASS(dpman));
mode = g_hash_table_lookup(oclass->modes, modename);
g_return_val_if_fail (mode != NULL, FALSE);
if (GST_DPMAN_MODE(dpman) == mode) {
GST_DEBUG(GST_CAT_PARAMS, "mode %s already set\n", modename);
return TRUE;
}
GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename);
if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){
GST_DPMAN_TEARDOWNFUNC(dpman)(dpman);
}
GST_DPMAN_MODE(dpman) = mode;
if (GST_DPMAN_SETUPFUNC(dpman)){
GST_DPMAN_SETUPFUNC(dpman)(dpman);
}
return TRUE;
}
/**
* gst_dpman_set_parent
* @dpman: GstDParamManager instance
* @parent: the element that this GstDParamManager belongs to
*
*/
void
gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent)
{
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
g_return_if_fail (parent != NULL);
g_return_if_fail (GST_IS_ELEMENT (parent));
g_hash_table_insert(_element_registry, parent, dpman);
gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent));
g_signal_connect(G_OBJECT(parent), "state_change",
G_CALLBACK (gst_dpman_state_change), dpman);
}
/**
* gst_dpman_get_manager
* @parent: the element that the desired GstDParamManager belongs to
*
* Returns: the GstDParamManager which belongs to this element or NULL
* if it doesn't exist
*/
GstDParamManager *
gst_dpman_get_manager (GstElement *parent)
{
GstDParamManager *dpman;
g_return_val_if_fail (parent != NULL, NULL);
g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent);
return dpman;
}
/**
* gst_dpman_set_rate_change_pad
* @dpman: GstDParamManager instance
* @pad: the pad which may have a "rate" caps property
*
*/
void
gst_dpman_set_rate_change_pad(GstDParamManager *dpman, GstPad *pad)
{
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_signal_connect(G_OBJECT(pad), "caps_changed",
G_CALLBACK (gst_dpman_caps_changed), dpman);
}
static GstDParamWrapper*
gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name)
{
g_return_val_if_fail (dpman != NULL, NULL);
g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
g_return_val_if_fail (dparam_name != NULL, NULL);
return g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name);
}
static GstDParamWrapper*
gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method)
{
GstDParamWrapper* dpwrap;
g_return_val_if_fail (dpman != NULL, NULL);
g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL);
g_return_val_if_fail (dparam_name != NULL, NULL);
g_return_val_if_fail(gst_dpman_get_wrapper(dpman, dparam_name) == NULL, NULL);
dpwrap = g_new0(GstDParamWrapper,1);
dpwrap->update_method = update_method;
dpwrap->value = g_new0(GValue,1);
g_value_init(dpwrap->value, type);
dpwrap->spec = g_new0(GstDParamSpec,1);
dpwrap->spec->dparam_name = dparam_name;
dpwrap->spec->min_val = g_new0(GValue,1);
dpwrap->spec->max_val = g_new0(GValue,1);
dpwrap->spec->default_val = g_new0(GValue,1);
g_value_init(dpwrap->spec->min_val, type);
g_value_init(dpwrap->spec->max_val, type);
g_value_init(dpwrap->spec->default_val, type);
g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap);
GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap);
return dpwrap;
}
static void
gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman)
{
GSList *dwraps;
GstDParam *dparam;
GstDParamWrapper *dpwrap;
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
if (state == GST_STATE_PLAYING){
GST_DEBUG(GST_CAT_PARAMS, "initialising params\n");
// force all params to be updated
dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
while (dwraps){
dpwrap = (GstDParamWrapper*)dwraps->data;
dparam = dpwrap->dparam;
if (dparam){
GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
if (dparam->spec){
g_value_copy(dparam->spec->default_val, GST_DPARAM_VALUE(dparam));
}
}
dwraps = g_slist_next(dwraps);
}
}
}
static void
gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman)
{
g_return_if_fail (caps != NULL);
g_return_if_fail (dpman != NULL);
g_return_if_fail (GST_IS_DPMAN (dpman));
GST_DPMAN_RATE(dpman) = gst_caps_get_int (caps, "rate");
GST_DEBUG(GST_CAT_PARAMS, "got caps change %d\n", GST_DPMAN_RATE(dpman));
}
static guint
gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp)
{
GSList *dwraps;
GstDParam *dparam;
GstDParamWrapper *dpwrap;
guint x;
g_return_val_if_fail (dpman != NULL, frames);
g_return_val_if_fail (GST_IS_DPMAN (dpman), frames);
// now check whether any passive dparams are ready for an update
dwraps = GST_DPMAN_DPARAMS_LIST(dpman);
while (dwraps){
dpwrap = (GstDParamWrapper*)dwraps->data;
dparam = dpwrap->dparam;
if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) &&
(GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp))){
// this will make dpwrap->value contain the latest value.
// now we just need to get it to the element
GST_DPARAM_DO_UPDATE(dparam, timestamp);
switch (dpwrap->update_method) {
// direct method - set the value directly in the struct of the element
case GST_DPMAN_DIRECT:
GST_DEBUG(GST_CAT_PARAMS, "doing direct update\n");
switch (G_VALUE_TYPE(dpwrap->value)){
case G_TYPE_CHAR:
*(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
break;
case G_TYPE_UCHAR:
*(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
break;
case G_TYPE_BOOLEAN:
*(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
break;
case G_TYPE_INT:
*(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
break;
case G_TYPE_UINT:
*(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
break;
case G_TYPE_LONG:
*(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
break;
case G_TYPE_ULONG:
*(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
break;
case G_TYPE_FLOAT:
*(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
break;
case G_TYPE_DOUBLE:
*(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
break;
case G_TYPE_POINTER:
*(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
break;
default:
break;
}
break;
// callback method - call the element's callback so it can do what it likes
case GST_DPMAN_CALLBACK:
GST_DEBUG(GST_CAT_PARAMS, "doing callback update\n");
GST_DPMAN_DO_UPDATE(dpwrap);
break;
// array method - generate an array of the right size
// with each value being the same (in synchronous update mode)
case GST_DPMAN_ARRAY:
GST_DEBUG(GST_CAT_PARAMS, "doing array update\n");
switch (G_VALUE_TYPE(dpwrap->value)){
case G_TYPE_CHAR:
(gchar*)dpwrap->update_data = g_new(gchar, frames);
*(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gchar*)dpwrap->update_data)[x] = *(gchar*)dpwrap->update_data;
break;
case G_TYPE_UCHAR:
(guchar*)dpwrap->update_data = g_new(guchar, frames);
*(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((guchar*)dpwrap->update_data)[x] = *(guchar*)dpwrap->update_data;
break;
case G_TYPE_BOOLEAN:
(gboolean*)dpwrap->update_data = g_new(gboolean, frames);
*(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gboolean*)dpwrap->update_data)[x] = *(gboolean*)dpwrap->update_data;
break;
case G_TYPE_INT:
(gint*)dpwrap->update_data = g_new(gint, frames);
*(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gint*)dpwrap->update_data)[x] = *(gint*)dpwrap->update_data;
break;
case G_TYPE_UINT:
(guint*)dpwrap->update_data = g_new(guint, frames);
*(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((guint*)dpwrap->update_data)[x] = *(guint*)dpwrap->update_data;
break;
case G_TYPE_LONG:
(glong*)dpwrap->update_data = g_new(glong, frames);
*(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((glong*)dpwrap->update_data)[x] = *(glong*)dpwrap->update_data;
break;
case G_TYPE_ULONG:
(gulong*)dpwrap->update_data = g_new(gulong, frames);
*(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gulong*)dpwrap->update_data)[x] = *(gulong*)dpwrap->update_data;
break;
case G_TYPE_FLOAT:
(gfloat*)dpwrap->update_data = g_new(gfloat, frames);
*(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gfloat*)dpwrap->update_data)[x] = *(gfloat*)dpwrap->update_data;
break;
case G_TYPE_DOUBLE:
(gdouble*)dpwrap->update_data = g_new(gdouble, frames);
*(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gdouble*)dpwrap->update_data)[x] = *(gdouble*)dpwrap->update_data;
break;
case G_TYPE_POINTER:
(gpointer*)dpwrap->update_data = g_new(gpointer, frames);
*(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value);
for (x = 1 ; x < frames ; x++)
((gpointer*)dpwrap->update_data)[x] = *(gpointer*)dpwrap->update_data;
break;
default:
break;
}
break;
default:
break;
}
}
dwraps = g_slist_next(dwraps);
}
return frames;
}
static guint
gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp)
{
return frames;
}
static guint
gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count)
{
return 0;
}

View file

@ -1,164 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdparammanager.h: Dynamic Parameter group functionality
*
* 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 __GST_DPMAN_H__
#define __GST_DPMAN_H__
#include <gst/gstobject.h>
#include <gst/gstprops.h>
#include <libs/control/gstdparamcommon.h>
#include <libs/control/gstdparam.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_DPMAN (gst_dpman_get_type ())
#define GST_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPMAN,GstDParamManager))
#define GST_DPMAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPMAN,GstDParamManager))
#define GST_IS_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPMAN))
#define GST_IS_DPMAN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPMAN))
#define GST_DPMAN_NAME(dpman) (GST_OBJECT_NAME(dpman))
#define GST_DPMAN_PARENT(dpman) (GST_OBJECT_PARENT(dpman))
#define GST_DPMAN_DPARAMS(dpman) ((dpman)->dparams)
#define GST_DPMAN_DPARAMS_LIST(dpman) ((dpman)->dparams_list)
#define GST_DPMAN_MODE_NAME(dpman) ((dpman)->mode_name)
#define GST_DPMAN_MODE(dpman) ((dpman)->mode)
#define GST_DPMAN_MODE_DATA(dpman) ((dpman)->mode_data)
#define GST_DPMAN_RATE(dpman) ((dpman)->rate)
typedef enum {
GST_DPMAN_CALLBACK,
GST_DPMAN_DIRECT,
GST_DPMAN_ARRAY,
} GstDPMUpdateMethod;
typedef struct _GstDParamManagerClass GstDParamManagerClass;
typedef struct _GstDPMMode GstDPMMode;
typedef struct _GstDParamWrapper GstDParamWrapper;
typedef guint (*GstDPMModePreProcessFunction) (GstDParamManager *dpman, guint frames, gint64 timestamp);
typedef guint (*GstDPMModeProcessFunction) (GstDParamManager *dpman, guint frame_count);
typedef void (*GstDPMModeSetupFunction) (GstDParamManager *dpman);
typedef void (*GstDPMModeTeardownFunction) (GstDParamManager *dpman);
typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data);
struct _GstDParamManager {
GstObject object;
GHashTable *dparams;
GSList *dparams_list;
gchar *mode_name;
GstDPMMode* mode;
gpointer mode_data;
gint64 timestamp;
guint rate;
};
struct _GstDParamManagerClass {
GstObjectClass parent_class;
GHashTable *modes;
/* signal callbacks */
};
struct _GstDPMMode {
GstDPMModePreProcessFunction preprocessfunc;
GstDPMModeProcessFunction processfunc;
GstDPMModeSetupFunction setupfunc;
GstDPMModeTeardownFunction teardownfunc;
};
struct _GstDParamWrapper {
GstDParamSpec* spec;
GValue *value;
GstDParam *dparam;
GstDPMUpdateMethod update_method;
gpointer update_data;
GstDPMUpdateFunction update_func;
};
#define GST_DPMAN_PREPROCESSFUNC(dpman) (((dpman)->mode)->preprocessfunc)
#define GST_DPMAN_PROCESSFUNC(dpman) (((dpman)->mode)->processfunc)
#define GST_DPMAN_SETUPFUNC(dpman) (((dpman)->mode)->setupfunc)
#define GST_DPMAN_TEARDOWNFUNC(dpman) (((dpman)->mode)->teardownfunc)
#define GST_DPMAN_PREPROCESS(dpman, buffer_size, timestamp) \
(GST_DPMAN_PREPROCESSFUNC(dpman)(dpman, buffer_size, timestamp))
#define GST_DPMAN_PROCESS(dpman, frame_count) \
(GST_DPMAN_PROCESSFUNC(dpman)(dpman, frame_count))
#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \
(frame_countdown-- || \
(frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count)))
#define GST_DPMAN_DO_UPDATE(dpwrap) ((dpwrap->update_func)(dpwrap->value, dpwrap->update_data))
void _gst_dpman_initialize();
GType gst_dpman_get_type (void);
GstDParamManager* gst_dpman_new (gchar *name, GstElement *parent);
void gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent);
GstDParamManager* gst_dpman_get_manager (GstElement *parent);
gboolean gst_dpman_add_required_dparam_callback (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
GstDPMUpdateFunction update_func,
gpointer update_data);
gboolean gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
gpointer update_data);
gboolean gst_dpman_add_required_dparam_array (GstDParamManager *dpman,
gchar *dparam_name,
GType type,
gpointer update_data);
void gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name);
gboolean gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam);
void gst_dpman_detach_dparam (GstDParamManager *dpman, gchar *dparam_name);
GstDParam* gst_dpman_get_dparam(GstDParamManager *dpman, gchar *name);
GType gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name);
GstDParamSpec** gst_dpman_list_dparam_specs(GstDParamManager *dpman);
GstDParamSpec* gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name);
void gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name);
void gst_dpman_set_rate_change_pad(GstDParamManager *dpman, GstPad *pad);
gboolean gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename);
void gst_dpman_register_mode (GstDParamManagerClass *klass,
gchar *modename,
GstDPMModePreProcessFunction preprocessfunc,
GstDPMModeProcessFunction processfunc,
GstDPMModeSetupFunction setupfunc,
GstDPMModeTeardownFunction teardownfunc);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_DPMAN_H__ */

View file

@ -1,83 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdplinearinterp.c: linear interpolation dynamic parameter
*
* 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 "gstdplinearinterp.h"
static void gst_dp_linint_class_init (GstDParamClass *klass);
static void gst_dp_linint_base_class_init (GstDParamClass *klass);
static void gst_dp_linint_init (GstDParam *dp_linint);
GType
gst_dp_linint_get_type(void) {
static GType dp_linint_type = 0;
if (!dp_linint_type) {
static const GTypeInfo dp_linint_info = {
sizeof(GstDParamClass),
(GBaseInitFunc)gst_dp_linint_base_class_init,
NULL,
(GClassInitFunc)gst_dp_linint_class_init,
NULL,
NULL,
sizeof(GstDParam),
0,
(GInstanceInitFunc)gst_dp_linint_init,
};
dp_linint_type = g_type_register_static(GST_TYPE_DPARAM, "GstDParamLinInterp", &dp_linint_info, 0);
}
return dp_linint_type;
}
static void
gst_dp_linint_base_class_init (GstDParamClass *klass)
{
}
static void
gst_dp_linint_class_init (GstDParamClass *klass)
{
}
static void
gst_dp_linint_init (GstDParam *dp_linint)
{
g_return_if_fail (dp_linint != NULL);
}
/**
* gst_dp_linint_new:
* @type: the type that this dp_linint will store
*
* Returns: a new instance of GstDParam
*/
GstDParam*
gst_dp_linint_new (GType type)
{
GstDParam *dparam;
GstDParamLinInterp *dp_linint;
dp_linint = g_object_new (gst_dp_linint_get_type (), NULL);
dparam = GST_DPARAM(dp_linint);
return dparam;
}

View file

@ -1,61 +0,0 @@
/* GStreamer
* Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
*
* gstdplinearinterp.h: linear interpolation dynamic parameter
*
* 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 __GST_DP_LININT_H__
#define __GST_DP_LININT_H__
#include <gst/gstobject.h>
#include "gstdparam.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_DP_LININT (gst_dp_linint_get_type ())
#define GST_DP_LININT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DP_LININT,GstDParamLinInterp))
#define GST_DP_LININT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DP_LININT,GstDParamLinInterp))
#define GST_IS_DP_LININT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DP_LININT))
#define GST_IS_DP_LININT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DP_LININT))
typedef struct _GstDParamLinInterp GstDParamLinInterp;
typedef struct _GstDParamLinInterpClass GstDParamLinInterpClass;
struct _GstDParamLinInterp {
GstDParam dparam;
};
struct _GstDParamLinInterpClass {
GstDParamClass parent_class;
/* signal callbacks */
};
GType gst_dp_linint_get_type (void);
GstDParam* gst_dp_linint_new (GType type);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_DP_LININT_H__ */

View file

@ -1,8 +0,0 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs
gbtest

View file

@ -1,22 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstgetbits.la
if HAVE_CPU_I386
GSTARCH_SRCS = gstgetbits_i386.s
else
GSTARCH_SRCS =
endif
libgstgetbits_la_SOURCES = gstgetbits.c gstgetbits_inl.h gstgetbits_generic.c $(GSTARCH_SRCS)
libgstgetbits_la_LIBADD = $(GST_LIBS)
libgstgetbits_la_CFLAGS = $(GST_CFLAGS) -funroll-all-loops -finline-functions -ffast-math
EXTRA_libgstgetbits_la_SOURCES = gstgetbits_i386.s
libgstgetbitsincludedir = $(includedir)/gst/libs/gstgetbits
libgstgetbitsinclude_HEADERS = gstgetbits.h
noinst_HEADERS = gstgetbits.h gstgetbits_inl.h
# check_PROGRAMS = gbtest

View file

@ -1,94 +0,0 @@
#include <stdlib.h>
#include "gstgetbits.h"
char *print_bits(unsigned long bits,int size) {
char *ret = (char *)malloc(size+1);
int i;
ret[size] = 0;
for (i=0;i<size;i++) {
if (bits & (1<<i))
ret[(size-1)-i] = '1';
else
ret[(size-1)-i] = '0';
}
return ret;
}
static unsigned char testbuffer[] =
{
0x11, 0x22, 0x44, 0x88, 0xCC, 0xEE,0xFF,0x11
};
void empty(gst_getbits_t *gb, void *data) {
printf("buffer empty\n");
gst_getbits_newbuf(gb,(unsigned char *)testbuffer, 7);
}
int main(int argc,char *argv[]) {
gst_getbits_t gb;
int i, j;
int bits;
gst_getbits_init(&gb, NULL, NULL);
gst_getbits_newbuf(&gb,(unsigned char *)testbuffer, 7);
for (i=0;i<7;i++) {
for (j=0;j<8;j++) {
printf("%lu",gst_getbits2(&gb));
gst_backbitsn(&gb, 1);
}
printf(" = %01x\n", testbuffer[i]);
}
gst_getbits_newbuf(&gb,(unsigned char *)testbuffer, 7);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000011 %lu\n",bits, gb.bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000022 %lu\n",bits, gb.bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000044 %lu\n",bits, gb.bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000088 %lu\n",bits, gb.bits);
bits = gst_getbits6(&gb);
printf("%08x <-> 00000033 %lu\n",bits, gb.bits);
gst_backbitsn(&gb, 16);
bits = gst_getbits10(&gb);
printf("%08x <-> 00000088 \n",bits);
gst_getbits_newbuf(&gb,(unsigned char *)testbuffer, 7);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000011 \n",bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000022 \n",bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000044 \n",bits);
bits = gst_getbits6(&gb);
printf("%08x <-> 00000022 \n",bits);
gst_backbitsn(&gb, 19);
bits = gst_getbits19(&gb);
printf("%08x <-> 00009122 \n",bits);
bits = gst_getbits10(&gb);
printf("%08x <-> 000000cc \n",bits);
gst_backbitsn(&gb, 8);
gst_backbitsn(&gb, 19);
gst_backbitsn(&gb, 8);
bits = gst_getbits19(&gb);
printf("%08x <-> 00012244 \n",bits);
bits = gst_getbits8(&gb);
printf("%08x <-> 00000088 \n",bits);
return 0;
}

View file

@ -1,214 +0,0 @@
#include "config.h"
#include "gstgetbits.h"
/* Defined in gstgetbits_i386.s */
extern unsigned long _gst_get1bit_i386(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_getbits_i386(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_getbits_fast_i386(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_showbits_i386(gst_getbits_t *gb, unsigned long bits);
extern void _gst_flushbits_i386(gst_getbits_t *gb, unsigned long bits);
extern void _gst_getbits_back_i386(gst_getbits_t *gb, unsigned long bits);
/* Defined in gstgetbits_generic.c */
extern unsigned long _gst_getbits_int_cb(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_get1bit_int(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_getbits_int(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_getbits_fast_int(gst_getbits_t *gb, unsigned long bits);
extern unsigned long _gst_showbits_int(gst_getbits_t *gb, unsigned long bits);
extern void _gst_flushbits_int(gst_getbits_t *gb, unsigned long bits);
extern void _gst_getbits_back_int(gst_getbits_t *gb, unsigned long bits);
unsigned long gst_getbits_nBitMask[] = {
0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe};
unsigned long _getbits_masks[] = {
0x00000000,
0x00000001, 0x00000003, 0x00000007, 0x0000000f,
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
};
#ifdef HAVE_LIBMMX
unsigned long _getbits_64_minus_index[] = {
64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,
40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,
16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 };
/* this routine taken from Intel AppNote AP-527:
"Using MMX[tm] Instructions to Get Bits From a Data Stream"
written in C with libmmx to *closely* mimic Intel's ASM implementation
this isn't as cycle-efficient, due to the simple fact that I must call
emms() at the end. all state must be kept in *gb, not in registers */
unsigned long _gst_getbits_mmx(gst_getbits_t *gb,unsigned long bits) {
signed long remaining;
unsigned long result;
/* NOTE: this is a code-size optimization Intel seems to have missed!
according to the MMX Programmer's Reference Manual, Chapter 5,
neither movd nor movq have any effect on the flags. that means you
can put them before the sub and jl in their code, which I've done
symbolically in this C code. gcc is probably going to lose horribly,
I'll do an inline asm version later. I've a point to prove ;-) */
/* find the right shift value, put it in mm3 */
movd_m2r(_getbits_64_minus_index[bits],mm3);
/* load the current quadword into mm0 */
movq_m2r(gb->qword,mm0);
/* copy it to mm2 */
movq_r2r(mm0,mm2);
remaining = gb->bits - bits;
if (remaining <= 0) {
unsigned long dword1,dword2;
/* shift the pointer by 64 bits (8 bytes) */
gb->ptr += 8;
/* add 64 to bits remaining, to bring it positive */
remaining += 64;
/* grab the first 32 bits from the buffer and swap them around */
dword1 = swab32(*(gb->ptr-8));
/* grab the second 32 bits, swap */
dword2 = swab32(*(gb->ptr-4));
/* put second dword in mm4 */
movd_m2r(dword2,mm4);
/* shift mm2 over to make room for new bits */
psrlq_r2r(mm3,mm2);
/* put first dword in mm1 */
movd_m2r(dword1,mm1);
/* shift second dword up 32 bits */
psrlq_i2r(32,mm4);
/* put the shift counter in mm3 */
movd_m2r(remaining,mm3);
/* combine the swapped data in mm4 */
por_r2r(mm1,mm4);
/* save off the bits in mm4 to mm0 */
movq_r2r(mm4,mm0);
/* get the new low-order bits in mm4, shifted by 'mm3' */
psrlq_r2r(mm3,mm4);
/* save off new remaining bits */
gb->bits = remaining;
/* combine bits into mm2 */
por_r2r(mm2,mm4);
/* save off the result */
movd_r2m(mm2,result);
/* get rid of the bits we just read */
psllq_r2r(mm1,mm0);
/* save off mm0 */
movq_r2m(mm0,gb->qword);
/* finished with MMX */
emms();
/* we have what we came for */
return(result);
} else {
/* load the number of bits requested into mm1 */
movd_m2r(bits,mm1);
/* shift the quadword in mm2 by 'mm3' bits */
psrlq_r2r(mm3,mm2);
/* update the number of valid bits */
gb->bits = remaining;
/* save off the remaining bits */
movd_r2m(mm2,result);
/* discard those bits in mm0 */
psllq_r2r(mm1,mm0);
/* save off mm0 */
movq_r2m(mm0,gb->qword);
/* finished with MMX */
emms();
/* we have what we came for */
return(result);
}
}
#endif /* HAVE_LIBMMX */
unsigned long _gst_getbyte(gst_getbits_t *gb, unsigned long bits) {
return *gb->ptr++;
}
/* initialize the getbits structure with the proper getbits func */
void gst_getbits_init(gst_getbits_t *gb, GstGetbitsCallback callback, void *data) {
gb->ptr = NULL;
gb->bits = 0;
gb->callback = callback;
gb->data = data;
#ifdef HAVE_LIBMMX
if (1) {
gb->getbits = _gst_getbits_mmx;
// gb->backbits = _gst_getbits_back_mmx;
// gb->backbytes = _gst_getbits_byteback_mmx;
// printf("gstgetbits: using MMX optimized versions\n");
} else
#endif /* HAVE_LIBMMX */
{
if (gb->callback) {
gb->getbits = _gst_getbits_int_cb;
gb->showbits = _gst_showbits_int;
gb->flushbits = _gst_flushbits_int;
gb->backbits = _gst_getbits_back_int;
// printf("gstgetbits: using callback versions\n");
}
else {
#ifdef HAVE_CPU_I386
gb->get1bit = _gst_get1bit_i386;
gb->getbits = _gst_getbits_i386;
gb->getbits_fast = _gst_getbits_fast_i386;
gb->getbyte = _gst_getbyte;
gb->show1bit = _gst_showbits_i386;
gb->showbits = _gst_showbits_i386;
gb->flushbits = _gst_flushbits_i386;
gb->backbits = _gst_getbits_back_i386;
// printf("gstgetbits: using i386 optimized versions\n");
#else
gb->get1bit = _gst_get1bit_int;
gb->getbits = _gst_getbits_int;
gb->getbits_fast = _gst_getbits_fast_int;
gb->getbyte = _gst_getbyte;
gb->show1bit = _gst_showbits_int;
gb->showbits = _gst_showbits_int;
gb->flushbits = _gst_flushbits_int;
gb->backbits = _gst_getbits_back_int;
// printf("gstgetbits: using normal versions\n");
#endif
}
}
}
/* set up the getbits structure with a new buffer */
void gst_getbits_newbuf(gst_getbits_t *gb,unsigned char *buffer, unsigned long len) {
gb->ptr = buffer;
gb->endptr = buffer+len;
gb->bits = 0;
#ifdef HAVE_LIBMMX
// gb->qword = 0;
#endif /* HAVE_LIBMMX */
}

View file

@ -1,149 +0,0 @@
#ifndef __GST_GETBITS_H__
#define __GST_GETBITS_H__
#include <stdio.h>
// getbits is critical, we need to forcibly disable DEBUG
#define GST_DEBUG_FORCE_DISABLE
#include <gst/gst.h>
/* disabled for now */
#undef HAVE_LIBMMX
#ifdef HAVE_LIBMMX
#include <mmx.h>
#endif /* HAVE_LIBMMX */
#ifdef HAVE_LIBSSE
#include <sse.h>
#endif /* HAVE_LIBSSE */
#define swab32(x) GUINT32_FROM_BE(x)
typedef struct _gst_getbits_t gst_getbits_t;
typedef void (*GstGetbitsCallback) (gst_getbits_t *gb, void *data);
/* breaks in structure show alignment on quadword boundaries */
/* FIXME: need to find out how to force GCC to align this to octwords */
struct _gst_getbits_t {
unsigned char *ptr;
unsigned long *longptr;
unsigned char *endptr;
unsigned long length;
long bits;
unsigned long dword;
unsigned long temp;
GstGetbitsCallback callback;
void *data;
unsigned long (*get1bit)(gst_getbits_t *gb, unsigned long bits);
unsigned long (*getbits)(gst_getbits_t *gb, unsigned long bits);
unsigned long (*getbits_fast)(gst_getbits_t *gb, unsigned long bits);
unsigned long (*getbyte)(gst_getbits_t *gb, unsigned long bits);
unsigned long (*show1bit)(gst_getbits_t *gb, unsigned long bits);
unsigned long (*showbits)(gst_getbits_t *gb, unsigned long bits);
void (*flushbits)(gst_getbits_t *gb, unsigned long bits);
void (*backbits)(gst_getbits_t *gb, unsigned long bits);
#ifdef HAVE_LIBMMX
mmx_t qword; /* qword */
#endif /* HAVE_LIBMMX */
#ifdef HAVE_LIBSSE
sse_t oword; /* oword */
#endif /* HAVE_LIBSSE */
};
#ifdef GST_GETBITS_INLINE
#include "gstgetbits_inl.h"
#else
void gst_getbits_init(gst_getbits_t *gb, GstGetbitsCallback callback, void *data);
void gst_getbits_newbuf(gst_getbits_t *gb, unsigned char *buffer, unsigned long len);
#define gst_getbits_bitoffset(gb) \
( \
(-(gb)->bits)&0x7 \
)
#define gst_getbits_align_byte(gb)
#define gst_getbits_bufferpos(gb) ((gb)->ptr)
#define gst_getbits_bytesleft(gb) ((gb)->endptr - (gb)->ptr)
#define gst_getbits_bitsleft(gb) (((gb)->endptr - (gb)->ptr)*8 - ((-(gb)->bits)&0x7))
#define gst_get1bit(gb) (((gb)->get1bit)(gb, 1))
#define gst_getbitsX(gb,bits) (((gb)->getbits)(gb,bits))
#define gst_getbits_fastX(gb,bits) (((gb)->getbits_fast)(gb,bits))
#define gst_show1bit(gb,bits) (((gb)->show1bit)(gb,bits))
#define gst_showbitsX(gb,bits) (((gb)->showbits)(gb,bits))
#define gst_flushbitsX(gb,bits) (((gb)->flushbits)(gb,bits))
#define gst_backbitsX(gb,bits) (((gb)->backbits)(gb,bits))
#define gst_getbyte(gb) (((gb)->getbyte)(gb,8))
#define gst_getbits_fastn(gb,n) gst_getbits_fastX(gb, n)
#define gst_getbitsn(gb,n) gst_getbitsX(gb, n)
#define gst_getbits1(gb) gst_get1bit(gb)
#define gst_getbits2(gb) gst_getbits_fastX(gb, 2)
#define gst_getbits3(gb) gst_getbits_fastX(gb, 3)
#define gst_getbits4(gb) gst_getbits_fastX(gb, 4)
#define gst_getbits5(gb) gst_getbits_fastX(gb, 5)
#define gst_getbits6(gb) gst_getbits_fastX(gb, 6)
#define gst_getbits7(gb) gst_getbits_fastX(gb, 7)
#define gst_getbits8(gb) gst_getbits_fastX(gb, 8)
#define gst_getbits9(gb) gst_getbits_fastX(gb, 9)
#define gst_getbits10(gb) gst_getbitsX(gb, 10)
#define gst_getbits11(gb) gst_getbitsX(gb, 11)
#define gst_getbits12(gb) gst_getbitsX(gb, 12)
#define gst_getbits13(gb) gst_getbitsX(gb, 13)
#define gst_getbits14(gb) gst_getbitsX(gb, 14)
#define gst_getbits15(gb) gst_getbitsX(gb, 15)
#define gst_getbits16(gb) gst_getbitsX(gb, 16)
#define gst_getbits17(gb) gst_getbitsX(gb, 17)
#define gst_getbits18(gb) gst_getbitsX(gb, 18)
#define gst_getbits19(gb) gst_getbitsX(gb, 19)
#define gst_getbits20(gb) gst_getbitsX(gb, 20)
#define gst_getbits21(gb) gst_getbitsX(gb, 21)
#define gst_getbits22(gb) gst_getbitsX(gb, 22)
#define gst_getbits23(gb) gst_getbitsX(gb, 23)
#define gst_showbitsn(gb,n) gst_showbitsX(gb, n)
#define gst_showbits1(gb) gst_show1bit(gb, 1)
#define gst_showbits2(gb) gst_showbitsX(gb, 2)
#define gst_showbits3(gb) gst_showbitsX(gb, 3)
#define gst_showbits4(gb) gst_showbitsX(gb, 4)
#define gst_showbits5(gb) gst_showbitsX(gb, 5)
#define gst_showbits6(gb) gst_showbitsX(gb, 6)
#define gst_showbits7(gb) gst_showbitsX(gb, 7)
#define gst_showbits8(gb) gst_showbitsX(gb, 8)
#define gst_showbits9(gb) gst_showbitsX(gb, 9)
#define gst_showbits10(gb) gst_showbitsX(gb, 10)
#define gst_showbits11(gb) gst_showbitsX(gb, 11)
#define gst_showbits12(gb) gst_showbitsX(gb, 12)
#define gst_showbits13(gb) gst_showbitsX(gb, 13)
#define gst_showbits14(gb) gst_showbitsX(gb, 14)
#define gst_showbits15(gb) gst_showbitsX(gb, 15)
#define gst_showbits16(gb) gst_showbitsX(gb, 16)
#define gst_showbits17(gb) gst_showbitsX(gb, 17)
#define gst_showbits18(gb) gst_showbitsX(gb, 18)
#define gst_showbits19(gb) gst_showbitsX(gb, 19)
#define gst_showbits20(gb) gst_showbitsX(gb, 20)
#define gst_showbits21(gb) gst_showbitsX(gb, 21)
#define gst_showbits22(gb) gst_showbitsX(gb, 22)
#define gst_showbits23(gb) gst_showbitsX(gb, 23)
#define gst_showbits24(gb) gst_showbitsX(gb, 24)
#define gst_showbits32(gb) gst_showbitsX(gb, 32)
#define gst_flushbitsn(gb,n) gst_flushbitsX(gb, n)
#define gst_flushbits32(gb) gst_flushbitsX(gb, 32)
#define gst_backbitsn(gb,n) gst_backbitsX(gb, n)
#define gst_backbits24(gb) gst_backbitsX(gb, 24)
#endif
#endif /* __GST_GETBITS_H__ */

View file

@ -1,116 +0,0 @@
#include "gstgetbits.h"
unsigned long _gst_getbits_int_cb(gst_getbits_t *gb, unsigned long bits);
unsigned long _gst_get1bit_int(gst_getbits_t *gb, unsigned long bits);
unsigned long _gst_getbits_int(gst_getbits_t *gb, unsigned long bits);
unsigned long _gst_getbits_fast_int(gst_getbits_t *gb, unsigned long bits);
unsigned long _gst_showbits_int(gst_getbits_t *gb, unsigned long bits);
void _gst_flushbits_int(gst_getbits_t *gb, unsigned long bits);
void _gst_getbits_back_int(gst_getbits_t *gb, unsigned long bits);
unsigned long _gst_getbits_int_cb(gst_getbits_t *gb, unsigned long bits) {
int result;
int bitsleft;
//printf("gst_getbits%lu %ld %p %08x\n", bits, gb->bits, gb->ptr, gb->dword);
if (!bits) return 0;
gb->bits -= bits;
result = gb->dword >> (32-bits);
if (gb->bits < 0) {
gb->ptr += 4;
bitsleft = (gb->endptr - gb->ptr)*8;
bits = -gb->bits;
gb->bits += (bitsleft>32? 32 : bitsleft);
if (gb->endptr <= gb->ptr) {
(gb->callback)(gb, gb->data);
gb->bits -= bits;
}
gb->dword = swab32(*((unsigned long *)(gb->ptr)));
result |= (gb->dword >> (32-bits));
}
gb->dword <<= bits;
return result;
}
unsigned long _gst_get1bit_int(gst_getbits_t *gb, unsigned long bits) {
unsigned char rval;
rval = *gb->ptr << gb->bits;
gb->bits++;
gb->ptr += (gb->bits>>3);
gb->bits &= 0x7;
GST_DEBUG (0,"getbits%ld, %08x\n", bits, rval);
return rval>>7;
}
unsigned long _gst_getbits_int(gst_getbits_t *gb, unsigned long bits) {
unsigned long rval;
if (bits == 0) return 0;
rval = swab32(*((unsigned long *)(gb->ptr)));
rval <<= gb->bits;
gb->bits += bits;
rval >>= (32-bits);
gb->ptr += (gb->bits>>3);
gb->bits &= 0x7;
GST_DEBUG (0,"getbits%ld, %08lx\n", bits, rval);
return rval;
}
unsigned long _gst_getbits_fast_int(gst_getbits_t *gb, unsigned long bits) {
unsigned long rval;
rval = (unsigned char) (gb->ptr[0] << gb->bits);
rval |= ((unsigned int) gb->ptr[1] << gb->bits)>>8;
rval <<= bits;
rval >>= 8;
gb->bits += bits;
gb->ptr += (gb->bits>>3);
gb->bits &= 0x7;
GST_DEBUG (0,"getbits%ld, %08lx\n", bits, rval);
return rval;
}
unsigned long _gst_showbits_int(gst_getbits_t *gb, unsigned long bits) {
unsigned long rval;
if (bits == 0) return 0;
rval = swab32(*((unsigned long *)(gb->ptr)));
rval <<= gb->bits;
rval >>= (32-bits);
GST_DEBUG (0,"showbits%ld, %08lx\n", bits, rval);
return rval;
}
void _gst_flushbits_int(gst_getbits_t *gb, unsigned long bits) {
gb->bits += bits;
gb->ptr += (gb->bits>>3);
gb->bits &= 0x7;
GST_DEBUG (0,"flushbits%ld\n", bits);
}
void _gst_getbits_back_int(gst_getbits_t *gb, unsigned long bits) {
gb->bits -= bits;
gb->ptr += (gb->bits>>3);
gb->bits &= 0x7;
}

View file

@ -1,115 +0,0 @@
.p2align 4,,7
.globl _gst_getbits_i386
.type _gst_getbits_i386,@function
_gst_getbits_i386:
cmpl $0,8(%esp)
jne .L39
xorl %eax,%eax
ret
.L39:
movl 4(%esp),%edx
movl (%edx),%ecx
movl (%ecx),%eax
bswap %eax
movl 16(%edx),%ecx
shll %cl, %eax
movl 8(%esp),%ecx
addl %ecx, 16(%edx)
negl %ecx
addl $32,%ecx
shrl %cl, %eax
movl 16(%edx),%ecx
sarl $3,%ecx
addl %ecx,(%edx)
andl $7,16(%edx)
ret
.p2align 4,,7
.globl _gst_getbits_fast_i386
.type _gst_getbits_fast_i386,@function
_gst_getbits_fast_i386:
movl 4(%esp),%edx
movl (%edx),%ecx
movzbl 1(%ecx),%eax
movb (%ecx), %ah
movl 16(%edx),%ecx
shlw %cl, %ax
movl 8(%esp),%ecx
addl %ecx, 16(%edx)
negl %ecx
addl $16,%ecx
shrl %cl, %eax
movl 16(%edx),%ecx
sarl $3,%ecx
addl %ecx,(%edx)
andl $7,16(%edx)
ret
.p2align 4,,7
.globl _gst_get1bit_i386
.type _gst_get1bit_i386,@function
_gst_get1bit_i386:
movl 4(%esp),%edx
movl (%edx),%ecx
movzbl (%ecx),%eax
movl 16(%edx),%ecx
incl %ecx
rolb %cl, %al
andb $1, %al
movl %ecx, 16(%edx)
andl $7,16(%edx)
sarl $3,%ecx
addl %ecx,(%edx)
ret
.p2align 4,,7
.globl _gst_showbits_i386
.type _gst_showbits_i386,@function
_gst_showbits_i386:
cmpl $0,8(%esp)
jne .L40
xorl %eax,%eax
ret
.L40:
movl 4(%esp),%edx
movl (%edx),%ecx
movl (%ecx), %eax
bswap %eax
movl 16(%edx),%ecx
shll %cl, %eax
movl 8(%esp),%ecx
negl %ecx
addl $32,%ecx
shrl %cl, %eax
ret
.p2align 4,,7
.globl _gst_flushbits_i386
.type _gst_flushbits_i386,@function
_gst_flushbits_i386:
movl 4(%esp),%ecx
movl 16(%ecx),%eax
addl 8(%esp),%eax
movl %eax, %edx
sarl $3,%eax
addl %eax,(%ecx)
andl $7, %edx
movl %edx, 16(%ecx)
ret
.p2align 4,,7
.globl _gst_getbits_back_i386
.type _gst_getbits_back_i386,@function
_gst_getbits_back_i386:
movl 4(%esp),%edx
movl 16(%edx),%ecx
subl 8(%esp),%ecx
movl %ecx, %eax
sarl $3,%ecx
addl %ecx,(%edx)
andl $7,%eax
movl %eax, 16(%edx)
ret

View file

@ -1,302 +0,0 @@
/*
* Copyright (c) 1995 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* Portions of this software Copyright (c) 1995 Brown University.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement
* is hereby granted, provided that the above copyright notice and the
* following two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
* BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
Changes to make the code reentrant:
deglobalized: curBits, curVidStream
deglobalized: bitOffset, bitLength, bitBuffer in vid_stream, not used
here
Additional changes:
-lsh@cs.brown.edu (Loring Holden)
*/
#ifndef __GST_GETBITS_INL_H__
#define __GST_GETBITS_INL_H__
#include <glib.h>
//#define GETBITS_DEBUG_ENABLED
//#define GETBITS_OVERRUN_ENABLED
#ifdef GETBITS_DEBUG_ENABLED
#define debug2(format,args...) g_print(format,##args)
#define debug(format,args...) g_print(format,##args),
#else
#define debug(format,args...)
#define debug2(format,args...)
#endif
#ifdef GETBITS_OVERRUN_ENABLED
#define checklength2(src, dst) (((unsigned char*)src)<(dst)?0:printf("overrun !! %p>=%p %ld %s %d\n", (src), (dst), (gb)->bits, __PRETTY_FUNCTION__, __LINE__))
#define checklength(src, dst) (((unsigned char*)src)<(dst)?0:printf("overrun !! %p>=%p %ld %s %d\n", (src), (dst), (gb)->bits, __PRETTY_FUNCTION__, __LINE__)),
#else
#define checklength(src, dst)
#define checklength2(src, dst)
#endif
#define swab32(x) GUINT32_FROM_BE(x)
/* External declarations for bitstream i/o operations. */
extern unsigned long gst_getbits_nBitMask[];
#define gst_getbits_init(gb, callback, data)
#define gst_getbits_newbuf(gb, buffer, len) \
{ \
(gb)->longptr = (unsigned long *)(buffer); \
(gb)->endptr = (unsigned char *)buffer+len; \
(gb)->length = len; \
(gb)->bits = 0; \
(gb)->dword = swab32(*(gb)->longptr); \
}
#define gst_getbits_bitoffset(gb) \
( \
debug("bitoffset: %ld %p\n", (gb)->bits, (gb)->longptr) \
(gb)->bits \
)
#define gst_getbits_bufferpos(gb) ((gb)->longptr)
#define gst_getbits_bytesleft(gb) ((gb)->endptr - (unsigned char*)(gb)->longptr)
#define gst_getbits_bitsleft(gb) (((gb)->endptr - (unsigned char*)(gb)->longptr)*8 - (gb)->bits)
#define gst_getbits1(gb) \
( \
((gb)->temp = (((gb)->dword & 0x80000000) != 0)), \
(gb)->dword <<= 1, \
(gb)->bits++, \
\
((gb)->bits & 0x20 ? ( \
(gb)->bits = 0, \
(gb)->longptr++, \
checklength((gb)->longptr, (gb)->endptr) \
((gb)->dword = swab32(*(gb)->longptr)) \
) \
:0), \
debug("getbits1 : %04lx %08lx %p\n", (gb)->temp, (gb)->dword, (gb)->longptr) \
(gb)->temp \
)
#define gst_getbits2(gb) \
( \
(gb)->bits += 2, \
\
((gb)->bits & 0x20 ? ( \
(gb)->bits -= 32, \
(gb)->longptr++, \
checklength((gb)->longptr, (gb)->endptr) \
((gb)->bits ? ( \
((gb)->dword |= \
(swab32(*(gb)->longptr) >> (2 - (gb)->bits))) \
) \
: 0 \
),( \
((gb)->temp = (((gb)->dword & 0xc0000000) >> 30)), \
((gb)->dword = swab32(*(gb)->longptr) << (gb)->bits)) \
) \
: ( \
((gb)->temp = (((gb)->dword & 0xc0000000) >> 30)), \
((gb)->dword <<= 2) \
) \
), \
debug("getbits2 : %04lx %08lx %p\n", (gb)->temp, (gb)->dword, (gb)->longptr) \
(gb)->temp \
)
#define gst_getbitsX(gb, num, mask, shift) \
( \
(gb)->bits += (num), \
\
((gb)->bits & 0x20 ? ( \
(gb)->bits -= 32, \
(gb)->longptr++, \
checklength((gb)->longptr, (gb)->endptr) \
((gb)->bits ? ( \
((gb)->dword |= (swab32(*(gb)->longptr) >> \
((num) - (gb)->bits))) \
) \
:0 \
), \
((gb)->temp = (((gb)->dword & (mask)) >> (shift))), \
((gb)->dword = swab32(*(gb)->longptr) << (gb)->bits) \
) \
: ( \
((gb)->temp = (((gb)->dword & mask) >> shift)), \
((gb)->dword <<= (num)) \
) \
), \
debug("getbits%-2d: %04lx %08lx %lu %p\n", num, (gb)->temp, (gb)->dword, mask, (gb)->longptr) \
(gb)->temp \
)
#define gst_getbits3(gb) gst_getbitsX(gb, 3, 0xe0000000UL, 29)
#define gst_getbits4(gb) gst_getbitsX(gb, 4, 0xf0000000UL, 28)
#define gst_getbits5(gb) gst_getbitsX(gb, 5, 0xf8000000UL, 27)
#define gst_getbits6(gb) gst_getbitsX(gb, 6, 0xfc000000UL, 26)
#define gst_getbits7(gb) gst_getbitsX(gb, 7, 0xfe000000UL, 25)
#define gst_getbits8(gb) gst_getbitsX(gb, 8, 0xff000000UL, 24)
#define gst_getbits9(gb) gst_getbitsX(gb, 9, 0xff800000UL, 23)
#define gst_getbits10(gb) gst_getbitsX(gb, 10, 0xffc00000UL, 22)
#define gst_getbits11(gb) gst_getbitsX(gb, 11, 0xffe00000UL, 21)
#define gst_getbits12(gb) gst_getbitsX(gb, 12, 0xfff00000UL, 20)
#define gst_getbits13(gb) gst_getbitsX(gb, 13, 0xfff80000UL, 19)
#define gst_getbits14(gb) gst_getbitsX(gb, 14, 0xfffc0000UL, 18)
#define gst_getbits15(gb) gst_getbitsX(gb, 15, 0xfffe0000UL, 17)
#define gst_getbits16(gb) gst_getbitsX(gb, 16, 0xffff0000UL, 16)
#define gst_getbits17(gb) gst_getbitsX(gb, 17, 0xffff8000UL, 15)
#define gst_getbits18(gb) gst_getbitsX(gb, 18, 0xffffc000UL, 14)
#define gst_getbits19(gb) gst_getbitsX(gb, 19, 0xffffe000UL, 13)
#define gst_getbits20(gb) gst_getbitsX(gb, 20, 0xfffff000UL, 12)
#define gst_getbits21(gb) gst_getbitsX(gb, 21, 0xfffff800UL, 11)
#define gst_getbits22(gb) gst_getbitsX(gb, 22, 0xfffffc00UL, 10)
#define gst_getbits32(gb) gst_getbitsX(gb, 32, 0xffffffffUL, 0)
#define gst_getbitsn(gb,num) gst_getbitsX(gb, (num), ((num) ? ((0xffffffffUL) << (32-(num))):0), (32-(num)))
#define gst_showbits32(gb) \
( \
((gb)->bits ? ( \
(gb)->dword | (swab32(*((gb)->longptr+1)) >> \
(32 - (gb)->bits)) \
) \
: ( \
(gb)->dword \
) \
) \
)
#define gst_showbitsX(gb, num, mask, shift) \
( \
((gb)->temp = (gb)->bits + num), \
((gb)->temp > 32 ? ( \
(gb)->temp -= 32, \
(((gb)->dword & mask) >> shift) | \
(swab32(*((gb)->longptr+1)) >> (shift + (num - (gb)->temp))) \
) \
: ( \
(((gb)->dword & mask) >> shift) \
) \
) \
)
#define gst_showbits1(gb) gst_showbitsX(gb, 1, 0x80000000, 31)
#define gst_showbits2(gb) gst_showbitsX(gb, 2, 0xc0000000, 30)
#define gst_showbits3(gb) gst_showbitsX(gb, 3, 0xe0000000, 29)
#define gst_showbits4(gb) gst_showbitsX(gb, 4, 0xf0000000, 28)
#define gst_showbits5(gb) gst_showbitsX(gb, 5, 0xf8000000, 27)
#define gst_showbits6(gb) gst_showbitsX(gb, 6, 0xfc000000, 26)
#define gst_showbits7(gb) gst_showbitsX(gb, 7, 0xfe000000, 25)
#define gst_showbits8(gb) gst_showbitsX(gb, 8, 0xff000000, 24)
#define gst_showbits9(gb) gst_showbitsX(gb, 9, 0xff800000, 23)
#define gst_showbits10(gb) gst_showbitsX(gb, 10, 0xffc00000, 22)
#define gst_showbits11(gb) gst_showbitsX(gb, 11, 0xffe00000, 21)
#define gst_showbits12(gb) gst_showbitsX(gb, 12, 0xfff00000, 20)
#define gst_showbits13(gb) gst_showbitsX(gb, 13, 0xfff80000, 19)
#define gst_showbits14(gb) gst_showbitsX(gb, 14, 0xfffc0000, 18)
#define gst_showbits15(gb) gst_showbitsX(gb, 15, 0xfffe0000, 17)
#define gst_showbits16(gb) gst_showbitsX(gb, 16, 0xffff0000, 16)
#define gst_showbits17(gb) gst_showbitsX(gb, 17, 0xffff8000, 15)
#define gst_showbits18(gb) gst_showbitsX(gb, 18, 0xffffc000, 14)
#define gst_showbits19(gb) gst_showbitsX(gb, 19, 0xffffe000, 13)
#define gst_showbits20(gb) gst_showbitsX(gb, 20, 0xfffff000, 12)
#define gst_showbits21(gb) gst_showbitsX(gb, 21, 0xfffff800, 11)
#define gst_showbits22(gb) gst_showbitsX(gb, 22, 0xfffffc00, 10)
#define gst_showbits23(gb) gst_showbitsX(gb, 23, 0xfffffe00, 9)
#define gst_showbits24(gb) gst_showbitsX(gb, 24, 0xffffff00, 8)
#define gst_showbits25(gb) gst_showbitsX(gb, 25, 0xffffff80, 7)
#define gst_showbits26(gb) gst_showbitsX(gb, 26, 0xffffffc0, 6)
#define gst_showbits27(gb) gst_showbitsX(gb, 27, 0xffffffe0, 5)
#define gst_showbits28(gb) gst_showbitsX(gb, 28, 0xfffffff0, 4)
#define gst_showbits29(gb) gst_showbitsX(gb, 29, 0xfffffff8, 3)
#define gst_showbits30(gb) gst_showbitsX(gb, 30, 0xfffffffc, 2)
#define gst_showbits31(gb) gst_showbitsX(gb, 31, 0xfffffffe, 1)
#define gst_showbitsn(gb,num) gst_showbitsX(gb, (num), ((0xffffffff) << (32-num)), (32-(num)))
#define gst_flushbits32(gb) \
{ \
(gb)->longptr++; \
checklength2((gb)->longptr, (gb)->endptr); \
(gb)->dword = swab32(*(gb)->longptr) << (gb)->bits; \
}
#define gst_flushbitsn(gb, num) \
{ \
(gb)->bits += num; \
\
if ((gb)->bits & 0x20) { \
(gb)->bits -= 32; \
(gb)->longptr++; \
checklength2((gb)->longptr, (gb)->endptr); \
(gb)->dword = swab32(*(gb)->longptr) << (gb)->bits; \
} \
else { \
(gb)->dword <<= num; \
} \
debug2("flushbits%-2d: %08lx %p\n", num, (gb)->dword, (gb)->longptr); \
}
#define gst_backbits24(gb) \
{ \
(gb)->bits -= 24; \
if ((gb)->bits < 0) { \
(gb)->bits += 32; \
(gb)->longptr--; \
} \
(gb)->dword = swab32(*(gb)->longptr) << (gb)->bits; \
}
#define gst_backbitsn(gb, num) \
{ \
(gb)->bits -= num; \
while ((gb)->bits < 0) { \
(gb)->bits += 32; \
(gb)->longptr--; \
} \
(gb)->dword = swab32(*(gb)->longptr) << (gb)->bits; \
debug2("backbits%-2d: %08lx %p\n", num, (gb)->dword, (gb)->longptr); \
}
#endif /* __GST_GETBITS_INL_H__ */

View file

@ -1,8 +0,0 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs
ieeetest

View file

@ -1,31 +0,0 @@
if HAVE_LIBMMX
GSTIDCTARCH_SRCS = mmxidct.S mmx32idct.c sseidct.S
else
GSTIDCTARCH_SRCS =
endif
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstidct.la
libgstidct_la_SOURCES = \
fastintidct.c \
floatidct.c \
gstidct.c \
intidct.c \
$(GSTIDCTARCH_SRCS)
libgstidctincludedir = $(includedir)/gst/libs/gstidct
libgstidctinclude_HEADERS = gstidct.h
check_PROGRAMS = ieeetest
ieeetest_SOURCES = ieeetest.c
ieeetest_LDADD = libgstidct.la
ieeetest_CFLAGS = $(GNOME_CFLAGS) $(GST_CFLAGS) $(XML_CFLAGS)
ieeetest_LDFLAGS = $(GNOME_LIBS) $(GST_LIBS)
noinst_HEADERS = dct.h
libgstidct_la_LIBADD = $(GST_LIBS)
libgstidct_la_CFLAGS = $(GST_CFLAGS) -finline-functions -ffast-math

View file

@ -1,48 +0,0 @@
This archive contains a quick & dirty implementation of the IEEE Standard
1180-1990 accuracy test for inverse DCT. It is not guaranteed to be
correct ... but if you find any bugs, please let me know (by email to
tgl@cs.cmu.edu).
The test harness consists of the C program ieeetest.c and shell script
doieee. For comparison purposes I have also supplied a copy of jrevdct.c,
the inverse DCT routine from release 4 of the Independent JPEG Group's
free JPEG software. (jrevdct.c is slightly modified from the IJG release
so that it will compile without the IJG include files.) jrevdct.c passes
the 1180 test --- or at least, this program thinks so. jrevdct.out is
the output from a test run.
Note that numerical results may vary somewhat across machines. This appears
to be mostly due to differing results from the cosine function.
INSTALLATION:
Check the Makefile, change CC and CFLAGS if needed. Then say "make".
If your C compiler is non-ANSI, you may need to change includes and/or
function headers.
To test a different IDCT routine, link with that routine instead of
jrevdct.o. You will need to modify dct.h and/or ieeetest.c if your
routine's calling convention is not in-place modification of an array
of 64 "short"s.
USAGE:
The standard test procedure is
doieee ieeetest >outputfile
Expect it to take a while (almost 80 minutes on my old 68030 box).
Each of the six passes will emit a row of 100 dots as it runs.
You can grep the output for the word FAILS if you just want to know
yea or nay.
LEGAL MUMBO-JUMBO:
I hereby release the test harness to the public domain.
Thomas G. Lane, 22 Nov 1993
IMPORTANT: jrevdct.c is NOT public domain, but is copyrighted free software
(not the same thing at all). It is subject to IJG's distribution terms, which
primarily state that if you incorporate it into a program you must acknowledge
IJG's contribution in your program documentation. For more details and the
complete IJG software, see the IJG FTP archive at ftp.uu.net, in directory
/graphics/jpeg.

View file

@ -1,34 +0,0 @@
/* define DCT types */
#include "config.h"
/*
* DCTSIZE underlying (1d) transform size
* DCTSIZE2 DCTSIZE squared
*/
#define DCTSIZE (8)
#define DCTSIZE2 (DCTSIZE*DCTSIZE)
#define EIGHT_BIT_SAMPLES /* needed in jrevdct.c */
typedef short DCTELEM; /* must be at least 16 bits */
typedef DCTELEM DCTBLOCK[DCTSIZE2];
typedef long INT32; /* must be at least 32 bits */
extern void gst_idct_int_idct();
extern void gst_idct_init_fast_int_idct (void);
extern void gst_idct_fast_int_idct (short *block);
#ifdef HAVE_LIBMMX
extern void gst_idct_mmx_idct (short *block);
extern void gst_idct_mmx32_idct (short *block);
extern void gst_idct_sse_idct (short *block);
#endif /* HAVE_LIBMMX */
extern void gst_idct_init_float_idct(void);
extern void gst_idct_float_idct (short *block);

View file

@ -1,15 +0,0 @@
# perform IEEE 1180 test series
# Typical usage:
# doieee >outfile
# where progname is ieeetest or a variant
for i in 1 2 3 4 5;
do
time ./ieeetest $i -256 255 1 10000
time ./ieeetest $i -5 5 1 10000
time ./ieeetest $i -300 300 1 10000
time ./ieeetest $i -256 255 -1 10000
time ./ieeetest $i -5 5 -1 10000
time ./ieeetest $i -300 300 -1 10000
done

View file

@ -1,207 +0,0 @@
/* idct.c, inverse fast discrete cosine transform */
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
/**********************************************************/
/* inverse two dimensional DCT, Chen-Wang algorithm */
/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) */
/* 32-bit integer arithmetic (8 bit coefficients) */
/* 11 mults, 29 adds per DCT */
/* sE, 18.8.91 */
/**********************************************************/
/* coefficients extended to 12 bit for IEEE1180-1990 */
/* compliance sE, 2.1.94 */
/**********************************************************/
/* this code assumes >> to be a two's-complement arithmetic */
/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */
#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */
#include "dct.h"
/* private data */
static short iclip[1024]; /* clipping table */
static short *iclp;
/* private prototypes */
static void idctrow (short *blk);
static void idctcol (short *blk);
/* row (horizontal) IDCT
*
* 7 pi 1
* dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l )
* l=0 8 2
*
* where: c[0] = 128
* c[1..7] = 128*sqrt(2)
*/
static void idctrow(blk)
short *blk;
{
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
/* shortcut */
if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) |
(x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3])))
{
blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3;
return;
}
x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */
/* first stage */
x8 = W7*(x4+x5);
x4 = x8 + (W1-W7)*x4;
x5 = x8 - (W1+W7)*x5;
x8 = W3*(x6+x7);
x6 = x8 - (W3-W5)*x6;
x7 = x8 - (W3+W5)*x7;
/* second stage */
x8 = x0 + x1;
x0 -= x1;
x1 = W6*(x3+x2);
x2 = x1 - (W2+W6)*x2;
x3 = x1 + (W2-W6)*x3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
/* third stage */
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181*(x4+x5)+128)>>8;
x4 = (181*(x4-x5)+128)>>8;
/* fourth stage */
blk[0] = (x7+x1)>>8;
blk[1] = (x3+x2)>>8;
blk[2] = (x0+x4)>>8;
blk[3] = (x8+x6)>>8;
blk[4] = (x8-x6)>>8;
blk[5] = (x0-x4)>>8;
blk[6] = (x3-x2)>>8;
blk[7] = (x7-x1)>>8;
}
/* column (vertical) IDCT
*
* 7 pi 1
* dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l )
* l=0 8 2
*
* where: c[0] = 1/1024
* c[1..7] = (1/1024)*sqrt(2)
*/
static void idctcol(blk)
short *blk;
{
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
/* shortcut */
if (!((x1 = (blk[8*4]<<8)) | (x2 = blk[8*6]) | (x3 = blk[8*2]) |
(x4 = blk[8*1]) | (x5 = blk[8*7]) | (x6 = blk[8*5]) | (x7 = blk[8*3])))
{
blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]=
iclp[(blk[8*0]+32)>>6];
return;
}
x0 = (blk[8*0]<<8) + 8192;
/* first stage */
x8 = W7*(x4+x5) + 4;
x4 = (x8+(W1-W7)*x4)>>3;
x5 = (x8-(W1+W7)*x5)>>3;
x8 = W3*(x6+x7) + 4;
x6 = (x8-(W3-W5)*x6)>>3;
x7 = (x8-(W3+W5)*x7)>>3;
/* second stage */
x8 = x0 + x1;
x0 -= x1;
x1 = W6*(x3+x2) + 4;
x2 = (x1-(W2+W6)*x2)>>3;
x3 = (x1+(W2-W6)*x3)>>3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
/* third stage */
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181*(x4+x5)+128)>>8;
x4 = (181*(x4-x5)+128)>>8;
/* fourth stage */
blk[8*0] = iclp[(x7+x1)>>14];
blk[8*1] = iclp[(x3+x2)>>14];
blk[8*2] = iclp[(x0+x4)>>14];
blk[8*3] = iclp[(x8+x6)>>14];
blk[8*4] = iclp[(x8-x6)>>14];
blk[8*5] = iclp[(x0-x4)>>14];
blk[8*6] = iclp[(x3-x2)>>14];
blk[8*7] = iclp[(x7-x1)>>14];
}
/* two dimensional inverse discrete cosine transform */
void gst_idct_fast_int_idct(block)
short *block;
{
int i;
for (i=0; i<8; i++)
idctrow(block+8*i);
for (i=0; i<8; i++)
idctcol(block+i);
}
void gst_idct_init_fast_int_idct()
{
int i;
iclp = iclip+512;
for (i= -512; i<512; i++)
iclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i);
}

View file

@ -1,102 +0,0 @@
/* Reference_IDCT.c, Inverse Discrete Fourier Transform, double precision */
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
/* Perform IEEE 1180 reference (64-bit floating point, separable 8x1
* direct matrix multiply) Inverse Discrete Cosine Transform
*/
/* Here we use math.h to generate constants. Compiler results may
vary a little */
#include <math.h>
#ifndef PI
# ifdef M_PI
# define PI M_PI
# else
# define PI 3.14159265358979323846
# endif
#endif
/* private data */
/* cosine transform matrix for 8x1 IDCT */
static double gst_idct_float_c[8][8];
/* initialize DCT coefficient matrix */
void gst_idct_init_float_idct()
{
int freq, time;
double scale;
for (freq=0; freq < 8; freq++)
{
scale = (freq == 0) ? sqrt(0.125) : 0.5;
for (time=0; time<8; time++)
gst_idct_float_c[freq][time] = scale*cos((PI/8.0)*freq*(time + 0.5));
}
}
/* perform IDCT matrix multiply for 8x8 coefficient block */
void gst_idct_float_idct(block)
short *block;
{
int i, j, k, v;
double partial_product;
double tmp[64];
for (i=0; i<8; i++)
for (j=0; j<8; j++)
{
partial_product = 0.0;
for (k=0; k<8; k++)
partial_product+= gst_idct_float_c[k][j]*block[8*i+k];
tmp[8*i+j] = partial_product;
}
/* Transpose operation is integrated into address mapping by switching
loop order of i and j */
for (j=0; j<8; j++)
for (i=0; i<8; i++)
{
partial_product = 0.0;
for (k=0; k<8; k++)
partial_product+= gst_idct_float_c[k][i]*tmp[8*k+j];
v = (int) floor(partial_product+0.5);
block[8*i+j] = (v<-256) ? -256 : ((v>255) ? 255 : v);
}
}

View file

@ -1,128 +0,0 @@
/* Gnome-Streamer
* 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 <gst/gst.h>
#include "gstidct.h"
#include "dct.h"
static void gst_idct_int_sparse_idct(short *data);
GstIDCT *gst_idct_new(GstIDCTMethod method)
{
GstIDCT *new = g_malloc(sizeof(GstIDCT));
new->need_transpose = FALSE;
if (method == GST_IDCT_DEFAULT) {
#ifdef HAVE_LIBMMX
if (gst_cpu_get_flags() & GST_CPU_FLAG_MMX) {
method = GST_IDCT_MMX;
}
/* disabled for now
if (gst_cpu_get_flags() & GST_CPU_FLAG_SSE) {
method = GST_IDCT_SSE;
}
*/
else
#endif /* HAVE_LIBMMX */
{
method = GST_IDCT_FAST_INT;
}
}
new->convert_sparse = gst_idct_int_sparse_idct;
switch (method) {
case GST_IDCT_FAST_INT:
GST_INFO (GST_CAT_PLUGIN_INFO, "using fast_int_idct");
gst_idct_init_fast_int_idct();
new->convert = gst_idct_fast_int_idct;
break;
case GST_IDCT_INT:
GST_INFO (GST_CAT_PLUGIN_INFO, "using int_idct");
new->convert = gst_idct_int_idct;
break;
case GST_IDCT_FLOAT:
GST_INFO (GST_CAT_PLUGIN_INFO, "using float_idct");
gst_idct_init_float_idct();
new->convert = gst_idct_float_idct;
break;
#ifdef HAVE_LIBMMX
case GST_IDCT_MMX:
GST_INFO (GST_CAT_PLUGIN_INFO, "using MMX_idct");
new->convert = gst_idct_mmx_idct;
new->need_transpose = TRUE;
break;
case GST_IDCT_MMX32:
GST_INFO (GST_CAT_PLUGIN_INFO, "using MMX32_idct");
new->convert = gst_idct_mmx32_idct;
new->need_transpose = TRUE;
break;
case GST_IDCT_SSE:
GST_INFO (GST_CAT_PLUGIN_INFO, "using SSE_idct");
new->convert = gst_idct_sse_idct;
new->need_transpose = TRUE;
break;
#endif /* HAVE_LIBMMX */
default:
GST_INFO (GST_CAT_PLUGIN_INFO, "method not supported");
g_free(new);
return NULL;
}
return new;
}
static void gst_idct_int_sparse_idct(short *data)
{
short val;
gint32 v, *dp = (guint32 *)data;
v = *data;
if (v < 0) {
val = -v;
val += (8 >> 1);
val /= 8;
val = -val;
}
else {
val = (v + (8 >> 1)) / 8;
}
v = (( val & 0xffff) | (val << 16));
dp[0] = v; dp[1] = v; dp[2] = v; dp[3] = v;
dp[4] = v; dp[5] = v; dp[6] = v; dp[7] = v;
dp[8] = v; dp[9] = v; dp[10] = v; dp[11] = v;
dp[12] = v; dp[13] = v; dp[14] = v; dp[15] = v;
dp[16] = v; dp[17] = v; dp[18] = v; dp[19] = v;
dp[20] = v; dp[21] = v; dp[22] = v; dp[23] = v;
dp[24] = v; dp[25] = v; dp[26] = v; dp[27] = v;
dp[28] = v; dp[29] = v; dp[30] = v; dp[31] = v;
}
void gst_idct_destroy(GstIDCT *idct)
{
g_return_if_fail(idct != NULL);
g_free(idct);
}

View file

@ -1,54 +0,0 @@
/* Gnome-Streamer
* 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 __GST_IDCT_H__
#define __GST_IDCT_H__
#include <glib.h>
typedef enum {
GST_IDCT_DEFAULT,
GST_IDCT_INT,
GST_IDCT_FAST_INT,
GST_IDCT_FLOAT,
GST_IDCT_MMX,
GST_IDCT_MMX32,
GST_IDCT_SSE,
} GstIDCTMethod;
typedef struct _GstIDCT GstIDCT;
typedef void (*GstIDCTFunction) (gshort *block);
#define GST_IDCT_TRANSPOSE(idct) ((idct)->need_transpose)
struct _GstIDCT {
/* private */
GstIDCTFunction convert;
GstIDCTFunction convert_sparse;
gboolean need_transpose;
};
GstIDCT *gst_idct_new(GstIDCTMethod method);
#define gst_idct_convert(idct, blocks) (idct)->convert((blocks))
#define gst_idct_convert_sparse(idct, blocks) (idct)->convert_sparse((blocks))
void gst_idct_destroy(GstIDCT *idct);
#endif /* __GST_IDCT_H__ */

View file

@ -1,335 +0,0 @@
/*
* ieeetest.c --- test IDCT code against the IEEE Std 1180-1990 spec
*
* Note that this does only one pass of the test.
* Six invocations of ieeetest are needed to complete the entire spec.
* The shell script "doieee" performs the complete test.
*
* Written by Tom Lane (tgl@cs.cmu.edu).
* Released to public domain 11/22/93.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <gst/gst.h>
#include "gstidct.h"
#include "dct.h"
/* prototypes */
void usage (char *msg);
long ieeerand (long L, long H);
void dct_init(void);
void ref_fdct(DCTELEM block[8][8]);
void ref_idct(DCTELEM block[8][8]);
/* error stat accumulators -- assume initialized to 0 */
long sumerrs[DCTSIZE2];
long sumsqerrs[DCTSIZE2];
int maxerr[DCTSIZE2];
char * meets (double val, double limit)
{
return ((fabs(val) <= limit) ? "meets" : "FAILS");
}
int
main(int argc, char **argv)
{
long minpix, maxpix, sign;
long curiter, niters;
int i, j;
double max, total;
int method;
DCTELEM block[DCTSIZE2]; /* random source data */
DCTELEM refcoefs[DCTSIZE2]; /* coefs from reference FDCT */
DCTELEM refout[DCTSIZE2]; /* output from reference IDCT */
DCTELEM testout[DCTSIZE2]; /* output from test IDCT */
GstIDCT *idct;
guint64 tscstart, tscmin = ~0, tscmax = 0;
guint64 tscstop;
/* Argument parsing --- not very bulletproof at all */
if (argc != 6) usage(NULL);
method = atoi(argv[1]);
minpix = atoi(argv[2]);
maxpix = atoi(argv[3]);
sign = atoi(argv[4]);
niters = atol(argv[5]);
gst_library_load("gstidct");
idct = gst_idct_new(method);
if (idct == 0) {
printf("method not available\n\n\n");
return 0;
}
dct_init();
/* Loop once per generated random-data block */
for (curiter = 0; curiter < niters; curiter++) {
/* generate a pseudo-random block of data */
for (i = 0; i < DCTSIZE2; i++)
block[i] = (DCTELEM) (ieeerand(-minpix,maxpix) * sign);
/* perform reference FDCT */
memcpy(refcoefs, block, sizeof(DCTELEM)*DCTSIZE2);
ref_fdct(refcoefs);
/* clip */
for (i = 0; i < DCTSIZE2; i++) {
if (refcoefs[i] < -2048) refcoefs[i] = -2048;
else if (refcoefs[i] > 2047) refcoefs[i] = 2047;
}
/* perform reference IDCT */
memcpy(refout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
ref_idct(refout);
/* clip */
for (i = 0; i < DCTSIZE2; i++) {
if (refout[i] < -256) refout[i] = -256;
else if (refout[i] > 255) refout[i] = 255;
}
/* perform test IDCT */
if (GST_IDCT_TRANSPOSE(idct)) {
for (j = 0; j < DCTSIZE; j++) {
for (i = 0; i < DCTSIZE; i++) {
testout[i*DCTSIZE+j] = refcoefs[j*DCTSIZE+i];
}
}
}
else {
memcpy(testout, refcoefs, sizeof(DCTELEM)*DCTSIZE2);
}
gst_trace_read_tsc(&tscstart);
gst_idct_convert(idct, testout);
gst_trace_read_tsc(&tscstop);
//printf("time %llu, %llu %lld\n", tscstart, tscstop, tscstop-tscstart);
if (tscstop - tscstart < tscmin) tscmin = tscstop-tscstart;
if (tscstop - tscstart > tscmax) tscmax = tscstop-tscstart;
/* clip */
for (i = 0; i < DCTSIZE2; i++) {
if (testout[i] < -256) testout[i] = -256;
else if (testout[i] > 255) testout[i] = 255;
}
/* accumulate error stats */
for (i = 0; i < DCTSIZE2; i++) {
register int err = testout[i] - refout[i];
sumerrs[i] += err;
sumsqerrs[i] += err * err;
if (err < 0) err = -err;
if (maxerr[i] < err) maxerr[i] = err;
}
if (curiter % 100 == 99) {
fprintf(stderr, ".");
fflush(stderr);
}
}
fprintf(stderr, "\n");
/* print results */
printf("IEEE test conditions: -L = %ld, +H = %ld, sign = %ld, #iters = %ld\n",
minpix, maxpix, sign, niters);
printf("Speed, min time %lld, max %lld\n", tscmin, tscmax);
printf("Peak absolute values of errors:\n");
for (i = 0, j = 0; i < DCTSIZE2; i++) {
if (j < maxerr[i]) j = maxerr[i];
printf("%4d", maxerr[i]);
if ((i%DCTSIZE) == DCTSIZE-1) printf("\n");
}
printf("Worst peak error = %d (%s spec limit 1)\n\n", j,
meets((double) j, 1.0));
printf("Mean square errors:\n");
max = total = 0.0;
for (i = 0; i < DCTSIZE2; i++) {
double err = (double) sumsqerrs[i] / ((double) niters);
total += (double) sumsqerrs[i];
if (max < err) max = err;
printf(" %8.4f", err);
if ((i%DCTSIZE) == DCTSIZE-1) printf("\n");
}
printf("Worst pmse = %.6f (%s spec limit 0.06)\n", max, meets(max, 0.06));
total /= (double) (64*niters);
printf("Overall mse = %.6f (%s spec limit 0.02)\n\n", total,
meets(total, 0.02));
printf("Mean errors:\n");
max = total = 0.0;
for (i = 0; i < DCTSIZE2; i++) {
double err = (double) sumerrs[i] / ((double) niters);
total += (double) sumerrs[i];
printf(" %8.4f", err);
if (err < 0.0) err = -err;
if (max < err) max = err;
if ((i%DCTSIZE) == DCTSIZE-1) printf("\n");
}
printf("Worst mean error = %.6f (%s spec limit 0.015)\n", max,
meets(max, 0.015));
total /= (double) (64*niters);
printf("Overall mean error = %.6f (%s spec limit 0.0015)\n\n", total,
meets(total, 0.0015));
/* test for 0 input giving 0 output */
memset(testout, 0, sizeof(DCTELEM)*DCTSIZE2);
gst_idct_convert(idct, testout);
for (i = 0, j=0; i < DCTSIZE2; i++) {
if (testout[i]) {
printf("Position %d of IDCT(0) = %d (FAILS)\n", i, testout[i]);
j++;
}
}
printf("%d elements of IDCT(0) were not zero\n\n\n", j);
exit(0);
return 0;
}
void usage (char *msg)
{
if (msg != NULL)
fprintf(stderr, "\nerror: %s\n", msg);
fprintf(stderr, "\n");
fprintf(stderr, "usage: ieeetest minpix maxpix sign niters\n");
fprintf(stderr, "\n");
fprintf(stderr, " test = 1 - 5\n");
fprintf(stderr, " minpix = -L value per IEEE spec\n");
fprintf(stderr, " maxpix = H value per IEEE spec\n");
fprintf(stderr, " sign = +1 for normal, -1 to run negated test\n");
fprintf(stderr, " niters = # iterations (10000 for full test)\n");
fprintf(stderr, "\n");
exit(1);
}
/* Pseudo-random generator specified by IEEE 1180 */
long ieeerand (long L, long H)
{
static long randx = 1;
static double z = (double) 0x7fffffff;
long i,j;
double x;
randx = (randx * 1103515245) + 12345;
i = randx & 0x7ffffffe;
x = ((double) i) / z;
x *= (L+H+1);
j = x;
return j-L;
}
/* Reference double-precision FDCT and IDCT */
/* The cosine lookup table */
/* coslu[a][b] = C(b)/2 * cos[(2a+1)b*pi/16] */
double coslu[8][8];
/* Routine to initialise the cosine lookup table */
void dct_init(void)
{
int a,b;
double tmp;
for(a=0;a<8;a++)
for(b=0;b<8;b++) {
tmp = cos((double)((a+a+1)*b) * (3.14159265358979323846 / 16.0));
if(b==0)
tmp /= sqrt(2.0);
coslu[a][b] = tmp * 0.5;
}
}
void ref_fdct (DCTELEM block[8][8])
{
int x,y,u,v;
double tmp, tmp2;
double res[8][8];
for (v=0; v<8; v++) {
for (u=0; u<8; u++) {
tmp = 0.0;
for (y=0; y<8; y++) {
tmp2 = 0.0;
for (x=0; x<8; x++) {
tmp2 += (double) block[y][x] * coslu[x][u];
}
tmp += coslu[y][v] * tmp2;
}
res[v][u] = tmp;
}
}
for (v=0; v<8; v++) {
for (u=0; u<8; u++) {
tmp = res[v][u];
if (tmp < 0.0) {
x = - ((int) (0.5 - tmp));
} else {
x = (int) (tmp + 0.5);
}
block[v][u] = (DCTELEM) x;
}
}
}
void ref_idct (DCTELEM block[8][8])
{
int x,y,u,v;
double tmp, tmp2;
double res[8][8];
for (y=0; y<8; y++) {
for (x=0; x<8; x++) {
tmp = 0.0;
for (v=0; v<8; v++) {
tmp2 = 0.0;
for (u=0; u<8; u++) {
tmp2 += (double) block[v][u] * coslu[x][u];
}
tmp += coslu[y][v] * tmp2;
}
res[y][x] = tmp;
}
}
for (v=0; v<8; v++) {
for (u=0; u<8; u++) {
tmp = res[v][u];
if (tmp < 0.0) {
x = - ((int) (0.5 - tmp));
} else {
x = (int) (tmp + 0.5);
}
block[v][u] = (DCTELEM) x;
}
}
}

View file

@ -1,391 +0,0 @@
/*
* jrevdct.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the basic inverse-DCT transformation subroutine.
*
* This implementation is based on an algorithm described in
* C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
* Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
* Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
* The primary algorithm described there uses 11 multiplies and 29 adds.
* We use their alternate method with 12 multiplies and 32 adds.
* The advantage of this method is that no data path contains more than one
* multiplication; this allows a very simple and accurate implementation in
* scaled fixed-point arithmetic, with a minimal number of shifts.
*/
#include "dct.h"
/* We assume that right shift corresponds to signed division by 2 with
* rounding towards minus infinity. This is correct for typical "arithmetic
* shift" instructions that shift in copies of the sign bit. But some
* C compilers implement >> with an unsigned shift. For these machines you
* must define RIGHT_SHIFT_IS_UNSIGNED.
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
* It is only applied with constant shift counts. SHIFT_TEMPS must be
* included in the variables of any routine using RIGHT_SHIFT.
*/
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS INT32 shift_temp;
#define RIGHT_SHIFT(x,shft) \
((shift_temp = (x)) < 0 ? \
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
(shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
#endif
/*
* This routine is specialized to the case DCTSIZE = 8.
*/
#if DCTSIZE != 8
Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
#endif
/*
* A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT
* on each column. Direct algorithms are also available, but they are
* much more complex and seem not to be any faster when reduced to code.
*
* The poop on this scaling stuff is as follows:
*
* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
* larger than the true IDCT outputs. The final outputs are therefore
* a factor of N larger than desired; since N=8 this can be cured by
* a simple right shift at the end of the algorithm. The advantage of
* this arrangement is that we save two multiplications per 1-D IDCT,
* because the y0 and y4 inputs need not be divided by sqrt(N).
*
* We have to do addition and subtraction of the integer inputs, which
* is no problem, and multiplication by fractional constants, which is
* a problem to do in integer arithmetic. We multiply all the constants
* by CONST_SCALE and convert them to integer constants (thus retaining
* CONST_BITS bits of precision in the constants). After doing a
* multiplication we have to divide the product by CONST_SCALE, with proper
* rounding, to produce the correct output. This division can be done
* cheaply as a right shift of CONST_BITS bits. We postpone shifting
* as long as possible so that partial sums can be added together with
* full fractional precision.
*
* The outputs of the first pass are scaled up by PASS1_BITS bits so that
* they are represented to better-than-integral precision. These outputs
* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
* with the recommended scaling. (To scale up 12-bit sample data further, an
* intermediate INT32 array would be needed.)
*
* To avoid overflow of the 32-bit intermediate results in pass 2, we must
* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
* shows that the values given below are the most effective.
*/
#ifdef EIGHT_BIT_SAMPLES
#define CONST_BITS 13
#define PASS1_BITS 2
#else
#define CONST_BITS 13
#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
#endif
#define ONE ((INT32) 1)
#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE. */
#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
* causing a lot of useless floating-point operations at run time.
* To get around this we use the following pre-calculated constants.
* If you change CONST_BITS you may want to add appropriate values.
* (With a reasonable C compiler, you can just rely on the FIX() macro...)
*/
#if CONST_BITS == 13
#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
#define FIX_0_541196100 FIX(0.541196100)
#define FIX_0_765366865 FIX(0.765366865)
#define FIX_0_899976223 FIX(0.899976223)
#define FIX_1_175875602 FIX(1.175875602)
#define FIX_1_501321110 FIX(1.501321110)
#define FIX_1_847759065 FIX(1.847759065)
#define FIX_1_961570560 FIX(1.961570560)
#define FIX_2_053119869 FIX(2.053119869)
#define FIX_2_562915447 FIX(2.562915447)
#define FIX_3_072711026 FIX(3.072711026)
#endif
/* Descale and correctly round an INT32 value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
* For 8-bit samples with the recommended scaling, all the variable
* and constant values involved are no more than 16 bits wide, so a
* 16x16->32 bit multiply can be used instead of a full 32x32 multiply;
* this provides a useful speedup on many machines.
* There is no way to specify a 16x16->32 multiply in portable C, but
* some C compilers will do the right thing if you provide the correct
* combination of casts.
* NB: for 12-bit samples, a full 32-bit multiplication will be needed.
*/
#ifdef EIGHT_BIT_SAMPLES
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const)))
#endif
#endif
#ifndef MULTIPLY /* default definition */
#define MULTIPLY(var,const) ((var) * (const))
#endif
/*
* Perform the inverse DCT on one block of coefficients.
*/
void
gst_idct_int_idct (DCTBLOCK data)
{
INT32 tmp0, tmp1, tmp2, tmp3;
INT32 tmp10, tmp11, tmp12, tmp13;
INT32 z1, z2, z3, z4, z5;
register DCTELEM *dataptr;
int rowctr;
SHIFT_TEMPS
/* Pass 1: process rows. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit this
* by short-circuiting the IDCT calculation for any row in which all
* the AC terms are zero. In that case each output is equal to the
* DC coefficient (with scale factor as needed).
* With typical images and quantization tables, half or more of the
* row DCT calculations can be simplified this way.
*/
if ((dataptr[1] | dataptr[2] | dataptr[3] | dataptr[4] |
dataptr[5] | dataptr[6] | dataptr[7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) (dataptr[0] << PASS1_BITS);
dataptr[0] = dcval;
dataptr[1] = dcval;
dataptr[2] = dcval;
dataptr[3] = dcval;
dataptr[4] = dcval;
dataptr[5] = dcval;
dataptr[6] = dcval;
dataptr[7] = dcval;
dataptr += DCTSIZE; /* advance pointer to next row */
continue;
}
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[2];
z3 = (INT32) dataptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[0] + (INT32) dataptr[4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[0] - (INT32) dataptr[4]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[7];
tmp1 = (INT32) dataptr[5];
tmp2 = (INT32) dataptr[3];
tmp3 = (INT32) dataptr[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
/* Pass 2: process columns. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
dataptr = data;
for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
/* Columns of zeroes can be exploited in the same way as we did with rows.
* However, the row calculation has created many nonzero AC terms, so the
* simplification applies less often (typically 5% to 10% of the time).
* On machines with very fast multiplication, it's possible that the
* test takes more time than it's worth. In that case this section
* may be commented out.
*/
#ifndef NO_ZERO_COLUMN_TEST
if ((dataptr[DCTSIZE*1] | dataptr[DCTSIZE*2] | dataptr[DCTSIZE*3] |
dataptr[DCTSIZE*4] | dataptr[DCTSIZE*5] | dataptr[DCTSIZE*6] |
dataptr[DCTSIZE*7]) == 0) {
/* AC terms all zero */
DCTELEM dcval = (DCTELEM) DESCALE((INT32) dataptr[0], PASS1_BITS+3);
dataptr[DCTSIZE*0] = dcval;
dataptr[DCTSIZE*1] = dcval;
dataptr[DCTSIZE*2] = dcval;
dataptr[DCTSIZE*3] = dcval;
dataptr[DCTSIZE*4] = dcval;
dataptr[DCTSIZE*5] = dcval;
dataptr[DCTSIZE*6] = dcval;
dataptr[DCTSIZE*7] = dcval;
dataptr++; /* advance pointer to next column */
continue;
}
#endif
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = (INT32) dataptr[DCTSIZE*2];
z3 = (INT32) dataptr[DCTSIZE*6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
tmp0 = ((INT32) dataptr[DCTSIZE*0] + (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp1 = ((INT32) dataptr[DCTSIZE*0] - (INT32) dataptr[DCTSIZE*4]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = (INT32) dataptr[DCTSIZE*7];
tmp1 = (INT32) dataptr[DCTSIZE*5];
tmp2 = (INT32) dataptr[DCTSIZE*3];
tmp3 = (INT32) dataptr[DCTSIZE*1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3);
dataptr++; /* advance pointer to next column */
}
}

View file

@ -1,783 +0,0 @@
/*
* idctmmx32.cpp
*
* Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
*
* This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
*
* FlasKMPEG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* FlasKMPEG 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// MMX32 iDCT algorithm (IEEE-1180 compliant) :: idct_mmx32()
//
// MPEG2AVI
// --------
// v0.16B33 initial release
//
// This was one of the harder pieces of work to code.
// Intel's app-note focuses on the numerical issues of the algorithm, but
// assumes the programmer is familiar with IDCT mathematics, leaving the
// form of the complete function up to the programmer's imagination.
//
// ALGORITHM OVERVIEW
// ------------------
// I played around with the code for quite a few hours. I came up
// with *A* working IDCT algorithm, however I'm not sure whether my routine
// is "the correct one." But rest assured, my code passes all six IEEE
// accuracy tests with plenty of margin.
//
// My IDCT algorithm consists of 4 steps:
//
// 1) IDCT-row transformation (using the IDCT-row function) on all 8 rows
// This yields an intermediate 8x8 matrix.
//
// 2) intermediate matrix transpose (mandatory)
//
// 3) IDCT-row transformation (2nd time) on all 8 rows of the intermediate
// matrix. The output is the final-result, in transposed form.
//
// 4) post-transformation matrix transpose
// (not necessary if the input-data is already transposed, this could
// be done during the MPEG "zig-zag" scan, but since my algorithm
// requires at least one transpose operation, why not re-use the
// transpose-code.)
//
// Although the (1st) and (3rd) steps use the SAME row-transform operation,
// the (3rd) step uses different shift&round constants (explained later.)
//
// Also note that the intermediate transpose (2) would not be neccessary,
// if the subsequent operation were a iDCT-column transformation. Since
// we only have the iDCT-row transform, we transpose the intermediate
// matrix and use the iDCT-row transform a 2nd time.
//
// I had to change some constants/variables for my method to work :
//
// As given by Intel, the #defines for SHIFT_INV_COL and RND_INV_COL are
// wrong. Not surprising since I'm not using a true column-transform
// operation, but the row-transform operation (as mentioned earlier.)
// round_inv_col[], which is given as "4 short" values, should have the
// same dimensions as round_inv_row[]. The corrected variables are
// shown.
//
// Intel's code defines a different table for each each row operation.
// The tables given are 0/4, 1/7, 2/6, and 5/3. My code only uses row#0.
// Using the other rows messes up the overall transform.
//
// IMPLEMENTATION DETAILs
// ----------------------
//
// I divided the algorithm's work into two subroutines,
// 1) idct_mmx32_rows() - transforms 8 rows, then transpose
// 2) idct_mmx32_cols() - transforms 8 rows, then transpose
// yields final result ("drop-in" direct replacement for INT32 IDCT)
//
// The 2nd function is a clone of the 1st, with changes made only to the
// shift&rounding instructions.
//
// In the 1st function (rows), the shift & round instructions use
// SHIFT_INV_ROW & round_inv_row[] (renamed to r_inv_row[])
//
// In the 2nd function (cols)-> r_inv_col[], and
// SHIFT_INV_COL & round_inv_col[] (renamed to r_inv_col[])
//
// Each function contains an integrated transpose-operator, which comes
// AFTER the primary transformation operation. In the future, I'll optimize
// the code to do more of the transpose-work "in-place". Right now, I've
// left the code as two subroutines and a main calling function, so other
// people can read the code more easily.
//
// liaor@umcc.ais.org http://members.tripod.com/~liaor
//
//;=============================================================================
//;
//; AP-922 http://developer.intel.com/vtune/cbts/strmsimd
//; These examples contain code fragments for first stage iDCT 8x8
//; (for rows) and first stage DCT 8x8 (for columns)
//;
//;=============================================================================
/*
mword typedef qword
qword ptr equ mword ptr */
#include <mmx.h>
#define BITS_INV_ACC 4 //; 4 or 5 for IEEE
// 5 yields higher accuracy, but lessens dynamic range on the input matrix
#define SHIFT_INV_ROW (16 - BITS_INV_ACC)
#define SHIFT_INV_COL (1 + BITS_INV_ACC +14 ) // changed from Intel's val)
//#define SHIFT_INV_COL (1 + BITS_INV_ACC )
#define RND_INV_ROW (1 << (SHIFT_INV_ROW-1))
#define RND_INV_COL (1 << (SHIFT_INV_COL-1))
#define RND_INV_CORR (RND_INV_COL - 1) //; correction -1.0 and round
//#define RND_INV_ROW (1024 * (6 - BITS_INV_ACC)) //; 1 << (SHIFT_INV_ROW-1)
//#define RND_INV_COL (16 * (BITS_INV_ACC - 3)) //; 1 << (SHIFT_INV_COL-1)
//.data
//Align 16
const static long r_inv_row[2] = { RND_INV_ROW, RND_INV_ROW};
const static long r_inv_col[2] = {RND_INV_COL, RND_INV_COL};
const static long r_inv_corr[2] = {RND_INV_CORR, RND_INV_CORR };
//const static short r_inv_col[4] =
// {RND_INV_COL, RND_INV_COL, RND_INV_COL, RND_INV_COL};
//const static short r_inv_corr[4] =
// {RND_INV_CORR, RND_INV_CORR, RND_INV_CORR, RND_INV_CORR};
/* constants for the forward DCT
//#define BITS_FRW_ACC 3 //; 2 or 3 for accuracy
//#define SHIFT_FRW_COL BITS_FRW_ACC
//#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17)
//#define RND_FRW_ROW (262144 * (BITS_FRW_ACC - 1)) //; 1 << (SHIFT_FRW_ROW-1)
const static __int64 one_corr = 0x0001000100010001;
const static long r_frw_row[2] = {RND_FRW_ROW, RND_FRW_ROW };
//const static short tg_1_16[4] = {13036, 13036, 13036, 13036 }; //tg * (2<<16) + 0.5
//const static short tg_2_16[4] = {27146, 27146, 27146, 27146 }; //tg * (2<<16) + 0.5
//const static short tg_3_16[4] = {-21746, -21746, -21746, -21746 }; //tg * (2<<16) + 0.5
//const static short cos_4_16[4] = {-19195, -19195, -19195, -19195 }; //cos * (2<<16) + 0.5
//const static short ocos_4_16[4] = {23170, 23170, 23170, 23170 }; //cos * (2<<15) + 0.5
//concatenated table, for forward DCT transformation
const static short tg_all_16[] = {
13036, 13036, 13036, 13036, // tg * (2<<16) + 0.5
27146, 27146, 27146, 27146, //tg * (2<<16) + 0.5
-21746, -21746, -21746, -21746, // tg * (2<<16) + 0.5
-19195, -19195, -19195, -19195, //cos * (2<<16) + 0.5
23170, 23170, 23170, 23170 }; //cos * (2<<15) + 0.5
#define tg_1_16 (tg_all_16 + 0)
#define tg_2_16 (tg_all_16 + 8)
#define tg_3_16 (tg_all_16 + 16)
#define cos_4_16 (tg_all_16 + 24)
#define ocos_4_16 (tg_all_16 + 32)
*/
/*
;=============================================================================
;
; The first stage iDCT 8x8 - inverse DCTs of rows
;
;-----------------------------------------------------------------------------
; The 8-point inverse DCT direct algorithm
;-----------------------------------------------------------------------------
;
; static const short w[32] = {
; FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16),
; FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16),
; FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16),
; FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16),
; FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16),
; FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16),
; FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16),
; FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) };
;
; #define DCT_8_INV_ROW(x, y)
;{
; int a0, a1, a2, a3, b0, b1, b2, b3;
;
; a0 =x[0]*w[0]+x[2]*w[1]+x[4]*w[2]+x[6]*w[3];
; a1 =x[0]*w[4]+x[2]*w[5]+x[4]*w[6]+x[6]*w[7];
; a2 = x[0] * w[ 8] + x[2] * w[ 9] + x[4] * w[10] + x[6] * w[11];
; a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15];
; b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19];
; b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23];
; b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27];
; b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31];
;
; y[0] = SHIFT_ROUND ( a0 + b0 );
; y[1] = SHIFT_ROUND ( a1 + b1 );
; y[2] = SHIFT_ROUND ( a2 + b2 );
; y[3] = SHIFT_ROUND ( a3 + b3 );
; y[4] = SHIFT_ROUND ( a3 - b3 );
; y[5] = SHIFT_ROUND ( a2 - b2 );
; y[6] = SHIFT_ROUND ( a1 - b1 );
; y[7] = SHIFT_ROUND ( a0 - b0 );
;}
;
;-----------------------------------------------------------------------------
;
; In this implementation the outputs of the iDCT-1D are multiplied
; for rows 0,4 - by cos_4_16,
; for rows 1,7 - by cos_1_16,
; for rows 2,6 - by cos_2_16,
; for rows 3,5 - by cos_3_16
; and are shifted to the left for better accuracy
;
; For the constants used,
; FIX(float_const) = (short) (float_const * (1<<15) + 0.5)
;
;=============================================================================
;=============================================================================
IF _MMX ; MMX code
;=============================================================================
//; Table for rows 0,4 - constants are multiplied by cos_4_16
const short tab_i_04[] = {
16384, 16384, 16384, -16384, // ; movq-> w06 w04 w02 w00
21407, 8867, 8867, -21407, // w07 w05 w03 w01
16384, -16384, 16384, 16384, //; w14 w12 w10 w08
-8867, 21407, -21407, -8867, //; w15 w13 w11 w09
22725, 12873, 19266, -22725, //; w22 w20 w18 w16
19266, 4520, -4520, -12873, //; w23 w21 w19 w17
12873, 4520, 4520, 19266, //; w30 w28 w26 w24
-22725, 19266, -12873, -22725 };//w31 w29 w27 w25
//; Table for rows 1,7 - constants are multiplied by cos_1_16
const short tab_i_17[] = {
22725, 22725, 22725, -22725, // ; movq-> w06 w04 w02 w00
29692, 12299, 12299, -29692, // ; w07 w05 w03 w01
22725, -22725, 22725, 22725, //; w14 w12 w10 w08
-12299, 29692, -29692, -12299, //; w15 w13 w11 w09
31521, 17855, 26722, -31521, //; w22 w20 w18 w16
26722, 6270, -6270, -17855, //; w23 w21 w19 w17
17855, 6270, 6270, 26722, //; w30 w28 w26 w24
-31521, 26722, -17855, -31521}; // w31 w29 w27 w25
//; Table for rows 2,6 - constants are multiplied by cos_2_16
const short tab_i_26[] = {
21407, 21407, 21407, -21407, // ; movq-> w06 w04 w02 w00
27969, 11585, 11585, -27969, // ; w07 w05 w03 w01
21407, -21407, 21407, 21407, // ; w14 w12 w10 w08
-11585, 27969, -27969, -11585, // ;w15 w13 w11 w09
29692, 16819, 25172, -29692, // ;w22 w20 w18 w16
25172, 5906, -5906, -16819, // ;w23 w21 w19 w17
16819, 5906, 5906, 25172, // ;w30 w28 w26 w24
-29692, 25172, -16819, -29692}; // ;w31 w29 w27 w25
//; Table for rows 3,5 - constants are multiplied by cos_3_16
const short tab_i_35[] = {
19266, 19266, 19266, -19266, //; movq-> w06 w04 w02 w00
25172, 10426, 10426, -25172, //; w07 w05 w03 w01
19266, -19266, 19266, 19266, //; w14 w12 w10 w08
-10426, 25172, -25172, -10426, //; w15 w13 w11 w09
26722, 15137, 22654, -26722, //; w22 w20 w18 w16
22654, 5315, -5315, -15137, //; w23 w21 w19 w17
15137, 5315, 5315, 22654, //; w30 w28 w26 w24
-26722, 22654, -15137, -26722}; //; w31 w29 w27 w25
*/
// CONCATENATED TABLE, rows 0,1,2,3,4,5,6,7 (in order )
//
// In our implementation, however, we only use row0 !
//
static const short tab_i_01234567[] = {
//row0, this row is required
16384, 16384, 16384, -16384, // ; movq-> w06 w04 w02 w00
21407, 8867, 8867, -21407, // w07 w05 w03 w01
16384, -16384, 16384, 16384, //; w14 w12 w10 w08
-8867, 21407, -21407, -8867, //; w15 w13 w11 w09
22725, 12873, 19266, -22725, //; w22 w20 w18 w16
19266, 4520, -4520, -12873, //; w23 w21 w19 w17
12873, 4520, 4520, 19266, //; w30 w28 w26 w24
-22725, 19266, -12873, -22725, //w31 w29 w27 w25
// the rest of these rows (1-7), aren't used !
//row1
22725, 22725, 22725, -22725, // ; movq-> w06 w04 w02 w00
29692, 12299, 12299, -29692, // ; w07 w05 w03 w01
22725, -22725, 22725, 22725, //; w14 w12 w10 w08
-12299, 29692, -29692, -12299, //; w15 w13 w11 w09
31521, 17855, 26722, -31521, //; w22 w20 w18 w16
26722, 6270, -6270, -17855, //; w23 w21 w19 w17
17855, 6270, 6270, 26722, //; w30 w28 w26 w24
-31521, 26722, -17855, -31521, // w31 w29 w27 w25
//row2
21407, 21407, 21407, -21407, // ; movq-> w06 w04 w02 w00
27969, 11585, 11585, -27969, // ; w07 w05 w03 w01
21407, -21407, 21407, 21407, // ; w14 w12 w10 w08
-11585, 27969, -27969, -11585, // ;w15 w13 w11 w09
29692, 16819, 25172, -29692, // ;w22 w20 w18 w16
25172, 5906, -5906, -16819, // ;w23 w21 w19 w17
16819, 5906, 5906, 25172, // ;w30 w28 w26 w24
-29692, 25172, -16819, -29692, // ;w31 w29 w27 w25
//row3
19266, 19266, 19266, -19266, //; movq-> w06 w04 w02 w00
25172, 10426, 10426, -25172, //; w07 w05 w03 w01
19266, -19266, 19266, 19266, //; w14 w12 w10 w08
-10426, 25172, -25172, -10426, //; w15 w13 w11 w09
26722, 15137, 22654, -26722, //; w22 w20 w18 w16
22654, 5315, -5315, -15137, //; w23 w21 w19 w17
15137, 5315, 5315, 22654, //; w30 w28 w26 w24
-26722, 22654, -15137, -26722, //; w31 w29 w27 w25
//row4
16384, 16384, 16384, -16384, // ; movq-> w06 w04 w02 w00
21407, 8867, 8867, -21407, // w07 w05 w03 w01
16384, -16384, 16384, 16384, //; w14 w12 w10 w08
-8867, 21407, -21407, -8867, //; w15 w13 w11 w09
22725, 12873, 19266, -22725, //; w22 w20 w18 w16
19266, 4520, -4520, -12873, //; w23 w21 w19 w17
12873, 4520, 4520, 19266, //; w30 w28 w26 w24
-22725, 19266, -12873, -22725, //w31 w29 w27 w25
//row5
19266, 19266, 19266, -19266, //; movq-> w06 w04 w02 w00
25172, 10426, 10426, -25172, //; w07 w05 w03 w01
19266, -19266, 19266, 19266, //; w14 w12 w10 w08
-10426, 25172, -25172, -10426, //; w15 w13 w11 w09
26722, 15137, 22654, -26722, //; w22 w20 w18 w16
22654, 5315, -5315, -15137, //; w23 w21 w19 w17
15137, 5315, 5315, 22654, //; w30 w28 w26 w24
-26722, 22654, -15137, -26722, //; w31 w29 w27 w25
//row6
21407, 21407, 21407, -21407, // ; movq-> w06 w04 w02 w00
27969, 11585, 11585, -27969, // ; w07 w05 w03 w01
21407, -21407, 21407, 21407, // ; w14 w12 w10 w08
-11585, 27969, -27969, -11585, // ;w15 w13 w11 w09
29692, 16819, 25172, -29692, // ;w22 w20 w18 w16
25172, 5906, -5906, -16819, // ;w23 w21 w19 w17
16819, 5906, 5906, 25172, // ;w30 w28 w26 w24
-29692, 25172, -16819, -29692, // ;w31 w29 w27 w25
//row7
22725, 22725, 22725, -22725, // ; movq-> w06 w04 w02 w00
29692, 12299, 12299, -29692, // ; w07 w05 w03 w01
22725, -22725, 22725, 22725, //; w14 w12 w10 w08
-12299, 29692, -29692, -12299, //; w15 w13 w11 w09
31521, 17855, 26722, -31521, //; w22 w20 w18 w16
26722, 6270, -6270, -17855, //; w23 w21 w19 w17
17855, 6270, 6270, 26722, //; w30 w28 w26 w24
-31521, 26722, -17855, -31521}; // w31 w29 w27 w25
#define INP eax // pointer to (short *blk)
#define OUT ecx // pointer to output (temporary store space qwTemp[])
#define TABLE ebx // pointer to tab_i_01234567[]
#define round_inv_row edx
#define round_inv_col edx
#define ROW_STRIDE 8 // for 8x8 matrix transposer
// private variables and functions
//temporary storage space, 8x8 of shorts
__inline static void idct_mmx32_rows( short *blk ); // transform rows
__inline static void idct_mmx32_cols( short *blk ); // transform "columns"
// the "column" transform actually transforms rows, it is
// identical to the row-transform except for the ROUNDING
// and SHIFTING coefficients.
static void
idct_mmx32_rows( short *blk ) // transform all 8 rows of 8x8 iDCT block
{
int x;
short qwTemp[64];
short *out = &qwTemp[0];
short *inptr = blk;
// this subroutine performs two operations
// 1) iDCT row transform
// for( i = 0; i < 8; ++ i)
// DCT_8_INV_ROW_1( blk[i*8], qwTemp[i] );
//
// 2) transpose the matrix (which was stored in qwTemp[])
// qwTemp[] -> [8x8 matrix transpose] -> blk[]
for (x=0; x<8; x++) { // transform one row per iteration
movq_m2r(*(inptr), mm0); // 0 ; x3 x2 x1 x0
movq_m2r(*(inptr+4), mm1); // 1 ; x7 x6 x5 x4
movq_r2r(mm0, mm2); // 2 ; x3 x2 x1 x0
movq_m2r(*(tab_i_01234567), mm3); // 3 ; w06 w04 w02 w00
punpcklwd_r2r(mm1, mm0); // x5 x1 x4 x0
// ----------
movq_r2r(mm0, mm5); // 5 ; x5 x1 x4 x0
punpckldq_r2r(mm0, mm0); // x4 x0 x4 x0
movq_m2r(*(tab_i_01234567+4), mm4); // 4 ; w07 w05 w03 w01
punpckhwd_r2r(mm1, mm2); // 1 ; x7 x3 x6 x2
pmaddwd_r2r(mm0, mm3); // x4*w06+x0*w04 x4*w02+x0*w00
movq_r2r(mm2, mm6); // 6 ; x7 x3 x6 x2
movq_m2r(*(tab_i_01234567+16), mm1);// 1 ; w22 w20 w18 w16
punpckldq_r2r(mm2, mm2); // x6 x2 x6 x2
pmaddwd_r2r(mm2, mm4); // x6*w07+x2*w05 x6*w03+x2*w01
punpckhdq_r2r(mm5, mm5); // x5 x1 x5 x1
pmaddwd_m2r(*(tab_i_01234567+8), mm0);// x4*w14+x0*w12 x4*w10+x0*w08
punpckhdq_r2r(mm6, mm6); // x7 x3 x7 x3
movq_m2r(*(tab_i_01234567+20), mm7);// 7 ; w23 w21 w19 w17
pmaddwd_r2r(mm5, mm1); // x5*w22+x1*w20 x5*w18+x1*w16
paddd_m2r(*(r_inv_row), mm3);// +rounder
pmaddwd_r2r(mm6, mm7); // x7*w23+x3*w21 x7*w19+x3*w17
pmaddwd_m2r(*(tab_i_01234567+12), mm2);// x6*w15+x2*w13 x6*w11+x2*w09
paddd_r2r(mm4, mm3); // 4 ; a1=sum(even1) a0=sum(even0)
pmaddwd_m2r(*(tab_i_01234567+24), mm5);// x5*w30+x1*w28 x5*w26+x1*w24
movq_r2r(mm3, mm4); // 4 ; a1 a0
pmaddwd_m2r(*(tab_i_01234567+28), mm6);// x7*w31+x3*w29 x7*w27+x3*w25
paddd_r2r(mm7, mm1); // 7 ; b1=sum(odd1) b0=sum(odd0)
paddd_m2r(*(r_inv_row), mm0);// +rounder
psubd_r2r(mm1, mm3); // a1-b1 a0-b0
psrad_i2r(SHIFT_INV_ROW, mm3); // y6=a1-b1 y7=a0-b0
paddd_r2r(mm4, mm1); // 4 ; a1+b1 a0+b0
paddd_r2r(mm2, mm0); // 2 ; a3=sum(even3) a2=sum(even2)
psrad_i2r(SHIFT_INV_ROW, mm1); // y1=a1+b1 y0=a0+b0
paddd_r2r(mm6, mm5); // 6 ; b3=sum(odd3) b2=sum(odd2)
movq_r2r(mm0, mm4); // 4 ; a3 a2
paddd_r2r(mm5, mm0); // a3+b3 a2+b2
psubd_r2r(mm5, mm4); // 5 ; a3-b3 a2-b2
psrad_i2r(SHIFT_INV_ROW, mm4); // y4=a3-b3 y5=a2-b2
psrad_i2r(SHIFT_INV_ROW, mm0); // y3=a3+b3 y2=a2+b2
packssdw_r2r(mm3, mm4); // 3 ; y6 y7 y4 y5
packssdw_r2r(mm0, mm1); // 0 ; y3 y2 y1 y0
movq_r2r(mm4, mm7); // 7 ; y6 y7 y4 y5
psrld_i2r(16, mm4); // 0 y6 0 y4
movq_r2m(mm1, *(out)); // 1 ; save y3 y2 y1 y0
pslld_i2r(16, mm7); // y7 0 y5 0
por_r2r(mm4, mm7); // 4 ; y7 y6 y5 y4
// begin processing row 1
movq_r2m(mm7, *(out+4)); // 7 ; save y7 y6 y5 y4
inptr += 8;
out += 8;
}
// done with the iDCT row-transformation
// now we have to transpose the output 8x8 matrix
// 8x8 (OUT) -> 8x8't' (IN)
// the transposition is implemented as 4 sub-operations.
// 1) transpose upper-left quad
// 2) transpose lower-right quad
// 3) transpose lower-left quad
// 4) transpose upper-right quad
// mm0 = 1st row [ A B C D ] row1
// mm1 = 2nd row [ E F G H ] 2
// mm2 = 3rd row [ I J K L ] 3
// mm3 = 4th row [ M N O P ] 4
// 1) transpose upper-left quad
out = &qwTemp[0];
movq_m2r(*(out + ROW_STRIDE * 0), mm0);
movq_m2r(*(out + ROW_STRIDE * 1), mm1);
movq_r2r(mm0, mm4); // mm4 = copy of row1[A B C D]
movq_m2r(*(out + ROW_STRIDE * 2), mm2);
punpcklwd_r2r(mm1, mm0); // mm0 = [ 0 4 1 5]
movq_m2r(*(out + ROW_STRIDE * 3), mm3);
punpckhwd_r2r(mm1, mm4); // mm4 = [ 2 6 3 7]
movq_r2r(mm2, mm6);
punpcklwd_r2r(mm3, mm2); // mm2 = [ 8 12 9 13]
punpckhwd_r2r(mm3, mm6); // mm6 = 10 14 11 15]
movq_r2r(mm0, mm1); // mm1 = [ 0 4 1 5]
inptr = blk;
punpckldq_r2r(mm2, mm0); // final result mm0 = row1 [0 4 8 12]
movq_r2r(mm4, mm3); // mm3 = [ 2 6 3 7]
punpckhdq_r2r(mm2, mm1); // mm1 = final result mm1 = row2 [1 5 9 13]
movq_r2m(mm0, *(inptr + ROW_STRIDE * 0)); // store row 1
punpckldq_r2r(mm6, mm4); // final result mm4 = row3 [2 6 10 14]
// begin reading next quadrant (lower-right)
movq_m2r(*(out + ROW_STRIDE*4 + 4), mm0);
punpckhdq_r2r(mm6, mm3); // final result mm3 = row4 [3 7 11 15]
movq_r2m(mm4, *(inptr + ROW_STRIDE * 2)); // store row 3
movq_r2r(mm0, mm4); // mm4 = copy of row1[A B C D]
movq_r2m(mm1, *(inptr + ROW_STRIDE * 1)); // store row 2
movq_m2r(*(out + ROW_STRIDE*5 + 4), mm1);
movq_r2m(mm3, *(inptr + ROW_STRIDE * 3)); // store row 4
punpcklwd_r2r(mm1, mm0); // mm0 = [ 0 4 1 5]
// 2) transpose lower-right quadrant
// movq mm0, qword ptr [OUT + ROW_STRIDE*4 + 8]
// movq mm1, qword ptr [OUT + ROW_STRIDE*5 + 8]
// movq mm4, mm0; // mm4 = copy of row1[A B C D]
movq_m2r(*(out + ROW_STRIDE*6 + 4), mm2);
// punpcklwd mm0, mm1; // mm0 = [ 0 4 1 5]
punpckhwd_r2r(mm1, mm4); // mm4 = [ 2 6 3 7]
movq_m2r(*(out + ROW_STRIDE*7 + 4), mm3);
movq_r2r(mm2, mm6);
punpcklwd_r2r(mm3, mm2); // mm2 = [ 8 12 9 13]
movq_r2r(mm0, mm1); // mm1 = [ 0 4 1 5]
punpckhwd_r2r(mm3, mm6); // mm6 = 10 14 11 15]
movq_r2r(mm4, mm3); // mm3 = [ 2 6 3 7]
punpckldq_r2r(mm2, mm0); // final result mm0 = row1 [0 4 8 12]
punpckhdq_r2r(mm2, mm1); // mm1 = final result mm1 = row2 [1 5 9 13]
; // slot
movq_r2m(mm0, *(inptr + ROW_STRIDE*4 + 4)); // store row 1
punpckldq_r2r(mm6, mm4); // final result mm4 = row3 [2 6 10 14]
movq_m2r(*(out + ROW_STRIDE * 4 ), mm0);
punpckhdq_r2r(mm6, mm3); // final result mm3 = row4 [3 7 11 15]
movq_r2m(mm4, *(inptr + ROW_STRIDE*6 + 4)); // store row 3
movq_r2r(mm0, mm4); // mm4 = copy of row1[A B C D]
movq_r2m(mm1, *(inptr + ROW_STRIDE*5 + 4)); // store row 2
; // slot
movq_m2r(*(out + ROW_STRIDE * 5 ), mm1);
; // slot
movq_r2m(mm3, *(inptr + ROW_STRIDE*7 + 4)); // store row 4
punpcklwd_r2r(mm1, mm0); // mm0 = [ 0 4 1 5]
// 3) transpose lower-left
// movq mm0, qword ptr [OUT + ROW_STRIDE * 4 ]
// movq mm1, qword ptr [OUT + ROW_STRIDE * 5 ]
// movq mm4, mm0; // mm4 = copy of row1[A B C D]
movq_m2r(*(out + ROW_STRIDE * 6 ), mm2);
// punpcklwd mm0, mm1; // mm0 = [ 0 4 1 5]
punpckhwd_r2r(mm1, mm4); // mm4 = [ 2 6 3 7]
movq_m2r(*(out + ROW_STRIDE * 7 ), mm3);
movq_r2r(mm2, mm6);
punpcklwd_r2r(mm3, mm2); // mm2 = [ 8 12 9 13]
movq_r2r(mm0, mm1); // mm1 = [ 0 4 1 5]
punpckhwd_r2r(mm3, mm6); // mm6 = 10 14 11 15]
movq_r2r(mm4, mm3); // mm3 = [ 2 6 3 7]
punpckldq_r2r(mm2, mm0); // final result mm0 = row1 [0 4 8 12]
punpckhdq_r2r(mm2, mm1); // mm1 = final result mm1 = row2 [1 5 9 13]
;//slot
movq_r2m(mm0, *(inptr + ROW_STRIDE * 0 + 4 )); // store row 1
punpckldq_r2r(mm6, mm4); // final result mm4 = row3 [2 6 10 14]
// begin reading next quadrant (upper-right)
movq_m2r(*(out + ROW_STRIDE*0 + 4), mm0);
punpckhdq_r2r(mm6, mm3); // final result mm3 = row4 [3 7 11 15]
movq_r2m(mm4, *(inptr + ROW_STRIDE * 2 + 4)); // store row 3
movq_r2r(mm0, mm4); // mm4 = copy of row1[A B C D]
movq_r2m(mm1, *(inptr + ROW_STRIDE * 1 + 4)); // store row 2
movq_m2r(*(out + ROW_STRIDE*1 + 4), mm1);
movq_r2m(mm3, *(inptr + ROW_STRIDE * 3 + 4)); // store row 4
punpcklwd_r2r(mm1, mm0); // mm0 = [ 0 4 1 5]
// 2) transpose lower-right quadrant
// movq mm0, qword ptr [OUT + ROW_STRIDE*4 + 8]
// movq mm1, qword ptr [OUT + ROW_STRIDE*5 + 8]
// movq mm4, mm0; // mm4 = copy of row1[A B C D]
movq_m2r(*(out + ROW_STRIDE*2 + 4), mm2);
// punpcklwd mm0, mm1; // mm0 = [ 0 4 1 5]
punpckhwd_r2r(mm1, mm4); // mm4 = [ 2 6 3 7]
movq_m2r(*(out + ROW_STRIDE*3 + 4), mm3);
movq_r2r(mm2, mm6);
punpcklwd_r2r(mm3, mm2); // mm2 = [ 8 12 9 13]
movq_r2r(mm0, mm1); // mm1 = [ 0 4 1 5]
punpckhwd_r2r(mm3, mm6); // mm6 = 10 14 11 15]
movq_r2r(mm4, mm3); // mm3 = [ 2 6 3 7]
punpckldq_r2r(mm2, mm0); // final result mm0 = row1 [0 4 8 12]
punpckhdq_r2r(mm2, mm1); // mm1 = final result mm1 = row2 [1 5 9 13]
; // slot
movq_r2m(mm0, *(inptr + ROW_STRIDE*4)); // store row 1
punpckldq_r2r(mm6, mm4); // final result mm4 = row3 [2 6 10 14]
movq_r2m(mm1, *(inptr + ROW_STRIDE*5)); // store row 2
punpckhdq_r2r(mm6, mm3); // final result mm3 = row4 [3 7 11 15]
movq_r2m(mm4, *(inptr + ROW_STRIDE*6)); // store row 3
; // slot
movq_r2m(mm3, *(inptr + ROW_STRIDE*7)); // store row 4
; // slot
}
static void
idct_mmx32_cols( short *blk ) // transform all 8 cols of 8x8 iDCT block
{
int x;
short *inptr = blk;
// Despite the function's name, the matrix is transformed
// row by row. This function is identical to idct_mmx32_rows(),
// except for the SHIFT amount and ROUND_INV amount.
// this subroutine performs two operations
// 1) iDCT row transform
// for( i = 0; i < 8; ++ i)
// DCT_8_INV_ROW_1( blk[i*8], qwTemp[i] );
//
// 2) transpose the matrix (which was stored in qwTemp[])
// qwTemp[] -> [8x8 matrix transpose] -> blk[]
for (x=0; x<8; x++) { // transform one row per iteration
movq_m2r(*(inptr), mm0); // 0 ; x3 x2 x1 x0
movq_m2r(*(inptr+4), mm1); // 1 ; x7 x6 x5 x4
movq_r2r(mm0, mm2); // 2 ; x3 x2 x1 x0
movq_m2r(*(tab_i_01234567), mm3); // 3 ; w06 w04 w02 w00
punpcklwd_r2r(mm1, mm0); // x5 x1 x4 x0
// ----------
movq_r2r(mm0, mm5); // 5 ; x5 x1 x4 x0
punpckldq_r2r(mm0, mm0); // x4 x0 x4 x0
movq_m2r(*(tab_i_01234567+4), mm4); // 4 ; w07 w05 w03 w01
punpckhwd_r2r(mm1, mm2); // 1 ; x7 x3 x6 x2
pmaddwd_r2r(mm0, mm3); // x4*w06+x0*w04 x4*w02+x0*w00
movq_r2r(mm2, mm6); // 6 ; x7 x3 x6 x2
movq_m2r(*(tab_i_01234567+16), mm1);// 1 ; w22 w20 w18 w16
punpckldq_r2r(mm2, mm2); // x6 x2 x6 x2
pmaddwd_r2r(mm2, mm4); // x6*w07+x2*w05 x6*w03+x2*w01
punpckhdq_r2r(mm5, mm5); // x5 x1 x5 x1
pmaddwd_m2r(*(tab_i_01234567+8), mm0);// x4*w14+x0*w12 x4*w10+x0*w08
punpckhdq_r2r(mm6, mm6); // x7 x3 x7 x3
movq_m2r(*(tab_i_01234567+20), mm7);// 7 ; w23 w21 w19 w17
pmaddwd_r2r(mm5, mm1); // x5*w22+x1*w20 x5*w18+x1*w16
paddd_m2r(*(r_inv_col), mm3);// +rounder
pmaddwd_r2r(mm6, mm7); // x7*w23+x3*w21 x7*w19+x3*w17
pmaddwd_m2r(*(tab_i_01234567+12), mm2);// x6*w15+x2*w13 x6*w11+x2*w09
paddd_r2r(mm4, mm3); // 4 ; a1=sum(even1) a0=sum(even0)
pmaddwd_m2r(*(tab_i_01234567+24), mm5);// x5*w30+x1*w28 x5*w26+x1*w24
movq_r2r(mm3, mm4); // 4 ; a1 a0
pmaddwd_m2r(*(tab_i_01234567+28), mm6);// x7*w31+x3*w29 x7*w27+x3*w25
paddd_r2r(mm7, mm1); // 7 ; b1=sum(odd1) b0=sum(odd0)
paddd_m2r(*(r_inv_col), mm0);// +rounder
psubd_r2r(mm1, mm3); // a1-b1 a0-b0
psrad_i2r(SHIFT_INV_COL, mm3); // y6=a1-b1 y7=a0-b0
paddd_r2r(mm4, mm1); // 4 ; a1+b1 a0+b0
paddd_r2r(mm2, mm0); // 2 ; a3=sum(even3) a2=sum(even2)
psrad_i2r(SHIFT_INV_COL, mm1); // y1=a1+b1 y0=a0+b0
paddd_r2r(mm6, mm5); // 6 ; b3=sum(odd3) b2=sum(odd2)
movq_r2r(mm0, mm4); // 4 ; a3 a2
paddd_r2r(mm5, mm0); // a3+b3 a2+b2
psubd_r2r(mm5, mm4); // 5 ; a3-b3 a2-b2
psrad_i2r(SHIFT_INV_COL, mm4); // y4=a3-b3 y5=a2-b2
psrad_i2r(SHIFT_INV_COL, mm0); // y3=a3+b3 y2=a2+b2
packssdw_r2r(mm3, mm4); // 3 ; y6 y7 y4 y5
packssdw_r2r(mm0, mm1); // 0 ; y3 y2 y1 y0
movq_r2r(mm4, mm7); // 7 ; y6 y7 y4 y5
psrld_i2r(16, mm4); // 0 y6 0 y4
movq_r2m(mm1, *(inptr)); // 1 ; save y3 y2 y1 y0
pslld_i2r(16, mm7); // y7 0 y5 0
por_r2r(mm4, mm7); // 4 ; y7 y6 y5 y4
// begin processing row 1
movq_r2m(mm7, *(inptr+4)); // 7 ; save y7 y6 y5 y4
inptr += 8;
}
// done with the iDCT column-transformation
}
//
// public interface to MMX32 IDCT 8x8 operation
//
void
gst_idct_mmx32_idct( short *blk )
{
// 1) iDCT row transformation
idct_mmx32_rows( blk ); // 1) transform iDCT row, and transpose
// 2) iDCT column transformation
idct_mmx32_cols( blk ); // 2) transform iDCT row, and transpose
emms(); // restore processor state
// all done
}

View file

@ -1,740 +0,0 @@
/*
* the input data is tranposed and each 16 bit element in the 8x8 matrix
* is left aligned:
* for example in 11...1110000 format
* If the iDCT is of I macroblock then 0.5 needs to be added to the;DC Component
* (element[0][0] of the matrix)
*
* Notes:
* - the scratchN variables should be put on the stack to avoid
* reentrancy problems
*/
#ifdef PIC
#define pic_offset(a) a@GOTOFF(%ebx)
#else
#define pic_offset(a) a
#endif
/* extrn re_matrix */
.data
.align 16
.type preSC,@object
preSC: .short 16384,22725,21407,19266,16384,12873,8867,4520
.short 22725,31521,29692,26722,22725,17855,12299,6270
.short 21407,29692,27969,25172,21407,16819,11585,5906
.short 19266,26722,25172,22654,19266,15137,10426,5315
.short 16384,22725,21407,19266,16384,12873,8867,4520
.short 12873,17855,16819,15137,25746,20228,13933,7103
.short 17734,24598,23170,20853,17734,13933,9597,4892
.short 18081,25080,23624,21261,18081,14206,9785,4988
.size preSC,128
.align 8
.type x0005000200010001,@object
.size x0005000200010001,8
x0005000200010001:
.long 0x00010001,0x00050002
.align 8
.type x0040000000000000,@object
.size x0040000000000000,8
x0040000000000000:
.long 0, 0x00400000
.align 8
.type x5a825a825a825a82,@object
.size x5a825a825a825a82,8
x5a825a825a825a82:
.long 0x5a825a82, 0x5a825a82
.align 8
.type x539f539f539f539f,@object
.size x539f539f539f539f,8
x539f539f539f539f:
.long 0x539f539f,0x539f539f
.align 8
.type x4546454645464546,@object
.size x4546454645464546,8
x4546454645464546:
.long 0x45464546,0x45464546
.align 8
.type x61f861f861f861f8,@object
.size x61f861f861f861f8,8
x61f861f861f861f8:
.long 0x61f861f8,0x61f861f8
.type x0004000000000000,@object
.size x0004000000000000,8
x0004000000000000:
.long 0x00000000,0x00040000
.type x0000000000000004,@object
.size x0000000000000004,8
x0000000000000004:
.long 0x00000004,0x00000000
.align 8
.type scratch1,@object
.size scratch1,8
scratch1:
.long 0,0
.align 8
.type scratch3,@object
.size scratch3,8
scratch3:
.long 0,0
.align 8
.type scratch5,@object
.size scratch5,8
scratch5:
.long 0,0
.align 8
.type scratch7,@object
.size scratch7,8
scratch7:
.long 0,0
.type x0,@object
.size x0,8
x0:
.long 0,0
.align 8
.text
.align 4
.globl gst_idct_mmx_idct
.type gst_idct_mmx_idct,@function
gst_idct_mmx_idct:
pushl %ebp
movl %esp,%ebp
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
#ifdef PIC
call here
here: popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-here],%ebx
#endif
movl 8(%ebp),%esi /* source matrix */
movq (%esi), %mm0
paddw pic_offset(x0000000000000004), %mm0
movq 8(%esi), %mm1
psllw $4, %mm0
movq 16(%esi), %mm2
psllw $4, %mm1
movq 24(%esi), %mm3
psllw $4, %mm2
movq 32(%esi), %mm4
psllw $4, %mm3
movq 40(%esi), %mm5
psllw $4, %mm4
movq 48(%esi), %mm6
psllw $4, %mm5
movq 56(%esi), %mm7
psllw $4, %mm6
psllw $4, %mm7
movq %mm0, (%esi)
movq %mm1, 8(%esi)
movq %mm2,16(%esi)
movq %mm3,24(%esi)
movq %mm4,32(%esi)
movq %mm5,40(%esi)
movq %mm6,48(%esi)
movq %mm7,56(%esi)
movq 64(%esi), %mm0
movq 72(%esi), %mm1
psllw $4, %mm0
movq 80(%esi), %mm2
psllw $4, %mm1
movq 88(%esi), %mm3
psllw $4, %mm2
movq 96(%esi), %mm4
psllw $4, %mm3
movq 104(%esi), %mm5
psllw $4, %mm4
movq 112(%esi), %mm6
psllw $4, %mm5
movq 120(%esi), %mm7
psllw $4, %mm6
psllw $4, %mm7
movq %mm0,64(%esi)
movq %mm1,72(%esi)
movq %mm2,80(%esi)
movq %mm3,88(%esi)
movq %mm4,96(%esi)
movq %mm5,104(%esi)
movq %mm6,112(%esi)
movq %mm7,120(%esi)
leal pic_offset(preSC), %ecx
/* column 0: even part
* use V4, V12, V0, V8 to produce V22..V25
*/
movq 8*12(%ecx), %mm0 /* maybe the first mul can be done together */
/* with the dequantization in iHuff module */
pmulhw 8*12(%esi), %mm0 /* V12 */
movq 8*4(%ecx), %mm1
pmulhw 8*4(%esi), %mm1 /* V4 */
movq (%ecx), %mm3
psraw $1, %mm0 /* t64=t66 */
pmulhw (%esi), %mm3 /* V0 */
movq 8*8(%ecx), %mm5 /* duplicate V4 */
movq %mm1, %mm2 /* added 11/1/96 */
pmulhw 8*8(%esi),%mm5 /* V8 */
psubsw %mm0, %mm1 /* V16 */
pmulhw pic_offset(x5a825a825a825a82), %mm1 /* 23170 ->V18 */
paddsw %mm0, %mm2 /* V17 */
movq %mm2, %mm0 /* duplicate V17 */
psraw $1, %mm2 /* t75=t82 */
psraw $2, %mm0 /* t72 */
movq %mm3, %mm4 /* duplicate V0 */
paddsw %mm5, %mm3 /* V19 */
psubsw %mm5, %mm4 /* V20 ;mm5 free */
/* moved from the block below */
movq 8*10(%ecx), %mm7
psraw $1, %mm3 /* t74=t81 */
movq %mm3, %mm6 /* duplicate t74=t81 */
psraw $2, %mm4 /* t77=t79 */
psubsw %mm0, %mm1 /* V21 ; mm0 free */
paddsw %mm2, %mm3 /* V22 */
movq %mm1, %mm5 /* duplicate V21 */
paddsw %mm4, %mm1 /* V23 */
movq %mm3, 8*4(%esi) /* V22 */
psubsw %mm5, %mm4 /* V24; mm5 free */
movq %mm1, 8*12(%esi) /* V23 */
psubsw %mm2, %mm6 /* V25; mm2 free */
movq %mm4, (%esi) /* V24 */
/* keep mm6 alive all along the next block */
/* movq %mm6, 8*8(%esi) V25 */
/* column 0: odd part
* use V2, V6, V10, V14 to produce V31, V39, V40, V41
*/
/* moved above: movq 8*10(%ecx), %mm7 */
pmulhw 8*10(%esi), %mm7 /* V10 */
movq 8*6(%ecx), %mm0
pmulhw 8*6(%esi), %mm0 /* V6 */
movq 8*2(%ecx), %mm5
movq %mm7, %mm3 /* duplicate V10 */
pmulhw 8*2(%esi), %mm5 /* V2 */
movq 8*14(%ecx), %mm4
psubsw %mm0, %mm7 /* V26 */
pmulhw 8*14(%esi), %mm4 /* V14 */
paddsw %mm0, %mm3 /* V29 ; free mm0 */
movq %mm7, %mm1 /* duplicate V26 */
psraw $1, %mm3 /* t91=t94 */
pmulhw pic_offset(x539f539f539f539f),%mm7 /* V33 */
psraw $1, %mm1 /* t96 */
movq %mm5, %mm0 /* duplicate V2 */
psraw $2, %mm4 /* t85=t87 */
paddsw %mm4,%mm5 /* V27 */
psubsw %mm4, %mm0 /* V28 ; free mm4 */
movq %mm0, %mm2 /* duplicate V28 */
psraw $1, %mm5 /* t90=t93 */
pmulhw pic_offset(x4546454645464546),%mm0 /* V35 */
psraw $1, %mm2 /* t97 */
movq %mm5, %mm4 /* duplicate t90=t93 */
psubsw %mm2, %mm1 /* V32 ; free mm2 */
pmulhw pic_offset(x61f861f861f861f8),%mm1 /* V36 */
psllw $1, %mm7 /* t107 */
paddsw %mm3, %mm5 /* V31 */
psubsw %mm3, %mm4 /* V30 ; free mm3 */
pmulhw pic_offset(x5a825a825a825a82),%mm4 /* V34 */
nop
psubsw %mm1, %mm0 /* V38 */
psubsw %mm7, %mm1 /* V37 ; free mm7 */
psllw $1, %mm1 /* t114 */
/* move from the next block */
movq %mm6, %mm3 /* duplicate V25 */
/* move from the next block */
movq 8*4(%esi), %mm7 /* V22 */
psllw $1, %mm0 /* t110 */
psubsw %mm5, %mm0 /* V39 (mm5 needed for next block) */
psllw $2, %mm4 /* t112 */
/* moved from the next block */
movq 8*12(%esi), %mm2 /* V23 */
psubsw %mm0, %mm4 /* V40 */
paddsw %mm4, %mm1 /* V41; free mm0 */
/* moved from the next block */
psllw $1, %mm2 /* t117=t125 */
/* column 0: output butterfly */
/* moved above:
* movq %mm6, %mm3 duplicate V25
* movq 8*4(%esi), %mm7 V22
* movq 8*12(%esi), %mm2 V23
* psllw $1, %mm2 t117=t125
*/
psubsw %mm1, %mm6 /* tm6 */
paddsw %mm1, %mm3 /* tm8; free mm1 */
movq %mm7, %mm1 /* duplicate V22 */
paddsw %mm5, %mm7 /* tm0 */
movq %mm3, 8*8(%esi) /* tm8; free mm3 */
psubsw %mm5, %mm1 /* tm14; free mm5 */
movq %mm6, 8*6(%esi) /* tm6; free mm6 */
movq %mm2, %mm3 /* duplicate t117=t125 */
movq (%esi), %mm6 /* V24 */
paddsw %mm0, %mm2 /* tm2 */
movq %mm7, (%esi) /* tm0; free mm7 */
psubsw %mm0, %mm3 /* tm12; free mm0 */
movq %mm1, 8*14(%esi) /* tm14; free mm1 */
psllw $1, %mm6 /* t119=t123 */
movq %mm2, 8*2(%esi) /* tm2; free mm2 */
movq %mm6, %mm0 /* duplicate t119=t123 */
movq %mm3, 8*12(%esi) /* tm12; free mm3 */
paddsw %mm4, %mm6 /* tm4 */
/* moved from next block */
movq 8*5(%ecx), %mm1
psubsw %mm4, %mm0 /* tm10; free mm4 */
/* moved from next block */
pmulhw 8*5(%esi), %mm1 /* V5 */
movq %mm6, 8*4(%esi) /* tm4; free mm6 */
movq %mm0, 8*10(%esi) /* tm10; free mm0 */
/* column 1: even part
* use V5, V13, V1, V9 to produce V56..V59
*/
/* moved to prev block:
* movq 8*5(%ecx), %mm1
* pmulhw 8*5(%esi), %mm1 V5
*/
movq 8*13(%ecx), %mm7
psllw $1, %mm1 /* t128=t130 */
pmulhw 8*13(%esi), %mm7 /* V13 */
movq %mm1, %mm2 /* duplicate t128=t130 */
movq 8(%ecx), %mm3
pmulhw 8(%esi), %mm3 /* V1 */
movq 8*9(%ecx), %mm5
psubsw %mm7, %mm1 /* V50 */
pmulhw 8*9(%esi), %mm5 /* V9 */
paddsw %mm7, %mm2 /* V51 */
pmulhw pic_offset(x5a825a825a825a82), %mm1 /* 23170 ->V52 */
movq %mm2, %mm6 /* duplicate V51 */
psraw $1, %mm2 /* t138=t144 */
movq %mm3, %mm4 /* duplicate V1 */
psraw $2, %mm6 /* t136 */
paddsw %mm5, %mm3 /* V53 */
psubsw %mm5, %mm4 /* V54 ;mm5 free */
movq %mm3, %mm7 /* duplicate V53 */
/* moved from next block */
movq 8*11(%ecx), %mm0
psraw $1, %mm4 /* t140=t142 */
psubsw %mm6, %mm1 /* V55 ; mm6 free */
paddsw %mm2, %mm3 /* V56 */
movq %mm4, %mm5 /* duplicate t140=t142 */
paddsw %mm1, %mm4 /* V57 */
movq %mm3, 8*5(%esi) /* V56 */
psubsw %mm1, %mm5 /* V58; mm1 free */
movq %mm4, 8*13(%esi) /* V57 */
psubsw %mm2, %mm7 /* V59; mm2 free */
movq %mm5, 8*9(%esi) /* V58 */
/* keep mm7 alive all along the next block
* movq %mm7, 8(%esi) V59
* moved above
* movq 8*11(%ecx), %mm0
*/
pmulhw 8*11(%esi), %mm0 /* V11 */
movq 8*7(%ecx), %mm6
pmulhw 8*7(%esi), %mm6 /* V7 */
movq 8*15(%ecx), %mm4
movq %mm0, %mm3 /* duplicate V11 */
pmulhw 8*15(%esi), %mm4 /* V15 */
movq 8*3(%ecx), %mm5
psllw $1, %mm6 /* t146=t152 */
pmulhw 8*3(%esi), %mm5 /* V3 */
paddsw %mm6, %mm0 /* V63 */
/* note that V15 computation has a correction step:
* this is a 'magic' constant that rebiases the results to be closer to the
* expected result. this magic constant can be refined to reduce the error
* even more by doing the correction step in a later stage when the number
* is actually multiplied by 16
*/
paddw pic_offset(x0005000200010001), %mm4
psubsw %mm6, %mm3 /* V60 ; free mm6 */
psraw $1, %mm0 /* t154=t156 */
movq %mm3, %mm1 /* duplicate V60 */
pmulhw pic_offset(x539f539f539f539f), %mm1 /* V67 */
movq %mm5, %mm6 /* duplicate V3 */
psraw $2, %mm4 /* t148=t150 */
paddsw %mm4, %mm5 /* V61 */
psubsw %mm4, %mm6 /* V62 ; free mm4 */
movq %mm5, %mm4 /* duplicate V61 */
psllw $1, %mm1 /* t169 */
paddsw %mm0, %mm5 /* V65 -> result */
psubsw %mm0, %mm4 /* V64 ; free mm0 */
pmulhw pic_offset(x5a825a825a825a82), %mm4 /* V68 */
psraw $1, %mm3 /* t158 */
psubsw %mm6, %mm3 /* V66 */
movq %mm5, %mm2 /* duplicate V65 */
pmulhw pic_offset(x61f861f861f861f8), %mm3 /* V70 */
psllw $1, %mm6 /* t165 */
pmulhw pic_offset(x4546454645464546), %mm6 /* V69 */
psraw $1, %mm2 /* t172 */
/* moved from next block */
movq 8*5(%esi), %mm0 /* V56 */
psllw $1, %mm4 /* t174 */
/* moved from next block */
psraw $1, %mm0 /* t177=t188 */
nop
psubsw %mm3, %mm6 /* V72 */
psubsw %mm1, %mm3 /* V71 ; free mm1 */
psubsw %mm2, %mm6 /* V73 ; free mm2 */
/* moved from next block */
psraw $1, %mm5 /* t178=t189 */
psubsw %mm6, %mm4 /* V74 */
/* moved from next block */
movq %mm0, %mm1 /* duplicate t177=t188 */
paddsw %mm4, %mm3 /* V75 */
/* moved from next block */
paddsw %mm5, %mm0 /* tm1 */
/* location
* 5 - V56
* 13 - V57
* 9 - V58
* X - V59, mm7
* X - V65, mm5
* X - V73, mm6
* X - V74, mm4
* X - V75, mm3
* free mm0, mm1 & mm2
* moved above
* movq 8*5(%esi), %mm0 V56
* psllw $1, %mm0 t177=t188 ! new !!
* psllw $1, %mm5 t178=t189 ! new !!
* movq %mm0, %mm1 duplicate t177=t188
* paddsw %mm5, %mm0 tm1
*/
movq 8*13(%esi), %mm2 /* V57 */
psubsw %mm5, %mm1 /* tm15; free mm5 */
movq %mm0, 8(%esi) /* tm1; free mm0 */
psraw $1, %mm7 /* t182=t184 ! new !! */
/* save the store as used directly in the transpose
* movq %mm1, 120(%esi) tm15; free mm1
*/
movq %mm7, %mm5 /* duplicate t182=t184 */
psubsw %mm3, %mm7 /* tm7 */
paddsw %mm3, %mm5 /* tm9; free mm3 */
movq 8*9(%esi), %mm0 /* V58 */
movq %mm2, %mm3 /* duplicate V57 */
movq %mm7, 8*7(%esi) /* tm7; free mm7 */
psubsw %mm6, %mm3 /* tm13 */
paddsw %mm6, %mm2 /* tm3 ; free mm6 */
/* moved up from the transpose */
movq %mm3, %mm7
/* moved up from the transpose */
punpcklwd %mm1, %mm3
movq %mm0, %mm6 /* duplicate V58 */
movq %mm2, 8*3(%esi) /* tm3; free mm2 */
paddsw %mm4, %mm0 /* tm5 */
psubsw %mm4, %mm6 /* tm11; free mm4 */
/* moved up from the transpose */
punpckhwd %mm1, %mm7
movq %mm0, 8*5(%esi) /* tm5; free mm0 */
/* moved up from the transpose */
movq %mm5, %mm2
/* transpose - M4 part
* --------- ---------
* | M1 | M2 | | M1'| M3'|
* --------- --> ---------
* | M3 | M4 | | M2'| M4'|
* --------- ---------
* Two alternatives: use full mmword approach so the following code can be
* scheduled before the transpose is done without stores, or use the faster
* half mmword stores (when possible)
*/
movd %mm3, 8*9+4(%esi) /* MS part of tmt9 */
punpcklwd %mm6, %mm5
movd %mm7, 8*13+4(%esi) /* MS part of tmt13 */
punpckhwd %mm6, %mm2
movd %mm5, 8*9(%esi) /* LS part of tmt9 */
punpckhdq %mm3, %mm5 /* free mm3 */
movd %mm2, 8*13(%esi) /* LS part of tmt13 */
punpckhdq %mm7, %mm2 /* free mm7 */
/* moved up from the M3 transpose */
movq 8*8(%esi), %mm0
/* moved up from the M3 transpose */
movq 8*10(%esi), %mm1
/* moved up from the M3 transpose */
movq %mm0, %mm3
/* shuffle the rest of the data, and write it with 2 mmword writes */
movq %mm5, 8*11(%esi) /* tmt11 */
/* moved up from the M3 transpose */
punpcklwd %mm1, %mm0
movq %mm2, 8*15(%esi) /* tmt15 */
/* moved up from the M3 transpose */
punpckhwd %mm1, %mm3
/* transpose - M3 part
* moved up to previous code section
* movq 8*8(%esi), %mm0
* movq 8*10(%esi), %mm1
* movq %mm0, %mm3
* punpcklwd %mm1, %mm0
* punpckhwd %mm1, %mm3
*/
movq 8*12(%esi), %mm6
movq 8*14(%esi), %mm4
movq %mm6, %mm2
/* shuffle the data and write the lower parts of the transposed in 4 dwords */
punpcklwd %mm4, %mm6
movq %mm0, %mm1
punpckhdq %mm6, %mm1
movq %mm3, %mm7
punpckhwd %mm4, %mm2 /* free mm4 */
punpckldq %mm6, %mm0 /* free mm6 */
/* moved from next block */
movq 8*13(%esi), %mm4 /* tmt13 */
punpckldq %mm2, %mm3
punpckhdq %mm2, %mm7 /* free mm2 */
/* moved from next block */
movq %mm3, %mm5 /* duplicate tmt5 */
/* column 1: even part (after transpose)
* moved above
* movq %mm3, %mm5 duplicate tmt5
* movq 8*13(%esi), %mm4 tmt13
*/
psubsw %mm4, %mm3 /* V134 */
pmulhw pic_offset(x5a825a825a825a82), %mm3 /* 23170 ->V136 */
movq 8*9(%esi), %mm6 /* tmt9 */
paddsw %mm4, %mm5 /* V135 ; mm4 free */
movq %mm0, %mm4 /* duplicate tmt1 */
paddsw %mm6, %mm0 /* V137 */
psubsw %mm6, %mm4 /* V138 ; mm6 free */
psllw $2, %mm3 /* t290 */
psubsw %mm5, %mm3 /* V139 */
movq %mm0, %mm6 /* duplicate V137 */
paddsw %mm5, %mm0 /* V140 */
movq %mm4, %mm2 /* duplicate V138 */
paddsw %mm3, %mm2 /* V141 */
psubsw %mm3, %mm4 /* V142 ; mm3 free */
movq %mm0, 8*9(%esi) /* V140 */
psubsw %mm5, %mm6 /* V143 ; mm5 free */
/* moved from next block */
movq 8*11(%esi), %mm0 /* tmt11 */
movq %mm2, 8*13(%esi) /* V141 */
/* moved from next block */
movq %mm0, %mm2 /* duplicate tmt11 */
/* column 1: odd part (after transpose) */
/* moved up to the prev block
* movq 8*11(%esi), %mm0 tmt11
* movq %mm0, %mm2 duplicate tmt11
*/
movq 8*15(%esi), %mm5 /* tmt15 */
psubsw %mm7, %mm0 /* V144 */
movq %mm0, %mm3 /* duplicate V144 */
paddsw %mm7, %mm2 /* V147 ; free mm7 */
pmulhw pic_offset(x539f539f539f539f), %mm0 /* 21407-> V151 */
movq %mm1, %mm7 /* duplicate tmt3 */
paddsw %mm5, %mm7 /* V145 */
psubsw %mm5, %mm1 /* V146 ; free mm5 */
psubsw %mm1, %mm3 /* V150 */
movq %mm7, %mm5 /* duplicate V145 */
pmulhw pic_offset(x4546454645464546), %mm1 /* 17734-> V153 */
psubsw %mm2, %mm5 /* V148 */
pmulhw pic_offset(x61f861f861f861f8), %mm3 /* 25080-> V154 */
psllw $2, %mm0 /* t311 */
pmulhw pic_offset(x5a825a825a825a82), %mm5 /* 23170-> V152 */
paddsw %mm2, %mm7 /* V149 ; free mm2 */
psllw $1, %mm1 /* t313 */
nop /* without the nop - freeze here for one clock */
movq %mm3, %mm2 /* duplicate V154 */
psubsw %mm0, %mm3 /* V155 ; free mm0 */
psubsw %mm2, %mm1 /* V156 ; free mm2 */
/* moved from the next block */
movq %mm6, %mm2 /* duplicate V143 */
/* moved from the next block */
movq 8*13(%esi), %mm0 /* V141 */
psllw $1, %mm1 /* t315 */
psubsw %mm7, %mm1 /* V157 (keep V149) */
psllw $2, %mm5 /* t317 */
psubsw %mm1, %mm5 /* V158 */
psllw $1, %mm3 /* t319 */
paddsw %mm5, %mm3 /* V159 */
/* column 1: output butterfly (after transform)
* moved to the prev block
* movq %mm6, %mm2 duplicate V143
* movq 8*13(%esi), %mm0 V141
*/
psubsw %mm3, %mm2 /* V163 */
paddsw %mm3, %mm6 /* V164 ; free mm3 */
movq %mm4, %mm3 /* duplicate V142 */
psubsw %mm5, %mm4 /* V165 ; free mm5 */
movq %mm2, pic_offset(scratch7) /* out7 */
psraw $4, %mm6
psraw $4, %mm4
paddsw %mm5, %mm3 /* V162 */
movq 8*9(%esi), %mm2 /* V140 */
movq %mm0, %mm5 /* duplicate V141 */
/* in order not to perculate this line up,
* we read 72(%esi) very near to this location
*/
movq %mm6, 8*9(%esi) /* out9 */
paddsw %mm1, %mm0 /* V161 */
movq %mm3, pic_offset(scratch5) /* out5 */
psubsw %mm1, %mm5 /* V166 ; free mm1 */
movq %mm4, 8*11(%esi) /* out11 */
psraw $4, %mm5
movq %mm0, pic_offset(scratch3) /* out3 */
movq %mm2, %mm4 /* duplicate V140 */
movq %mm5, 8*13(%esi) /* out13 */
paddsw %mm7, %mm2 /* V160 */
/* moved from the next block */
movq 8(%esi), %mm0
psubsw %mm7, %mm4 /* V167 ; free mm7 */
/* moved from the next block */
movq 8*3(%esi), %mm7
psraw $4, %mm4
movq %mm2, pic_offset(scratch1) /* out1 */
/* moved from the next block */
movq %mm0, %mm1
movq %mm4, 8*15(%esi) /* out15 */
/* moved from the next block */
punpcklwd %mm7, %mm0
/* transpose - M2 parts
* moved up to the prev block
* movq 8(%esi), %mm0
* movq 8*3(%esi), %mm7
* movq %mm0, %mm1
* punpcklwd %mm7, %mm0
*/
movq 8*5(%esi), %mm5
punpckhwd %mm7, %mm1
movq 8*7(%esi), %mm4
movq %mm5, %mm3
/* shuffle the data and write the lower parts of the trasposed in 4 dwords */
movd %mm0, 8*8(%esi) /* LS part of tmt8 */
punpcklwd %mm4, %mm5
movd %mm1, 8*12(%esi) /* LS part of tmt12 */
punpckhwd %mm4, %mm3
movd %mm5, 8*8+4(%esi) /* MS part of tmt8 */
punpckhdq %mm5, %mm0 /* tmt10 */
movd %mm3, 8*12+4(%esi) /* MS part of tmt12 */
punpckhdq %mm3, %mm1 /* tmt14 */
/* transpose - M1 parts */
movq (%esi), %mm7
movq 8*2(%esi), %mm2
movq %mm7, %mm6
movq 8*4(%esi), %mm5
punpcklwd %mm2, %mm7
movq 8*6(%esi), %mm4
punpckhwd %mm2, %mm6 /* free mm2 */
movq %mm5, %mm3
punpcklwd %mm4, %mm5
punpckhwd %mm4, %mm3 /* free mm4 */
movq %mm7, %mm2
movq %mm6, %mm4
punpckldq %mm5, %mm7 /* tmt0 */
punpckhdq %mm5, %mm2 /* tmt2 ; free mm5 */
/* shuffle the rest of the data, and write it with 2 mmword writes */
punpckldq %mm3, %mm6 /* tmt4 */
/* moved from next block */
movq %mm2, %mm5 /* duplicate tmt2 */
punpckhdq %mm3, %mm4 /* tmt6 ; free mm3 */
/* moved from next block */
movq %mm0, %mm3 /* duplicate tmt10 */
/* column 0: odd part (after transpose)
*moved up to prev block
* movq %mm0, %mm3 duplicate tmt10
* movq %mm2, %mm5 duplicate tmt2
*/
psubsw %mm4, %mm0 /* V110 */
paddsw %mm4, %mm3 /* V113 ; free mm4 */
movq %mm0, %mm4 /* duplicate V110 */
paddsw %mm1, %mm2 /* V111 */
pmulhw pic_offset(x539f539f539f539f), %mm0 /* 21407-> V117 */
psubsw %mm1, %mm5 /* V112 ; free mm1 */
psubsw %mm5, %mm4 /* V116 */
movq %mm2, %mm1 /* duplicate V111 */
pmulhw pic_offset(x4546454645464546), %mm5 /* 17734-> V119 */
psubsw %mm3, %mm2 /* V114 */
pmulhw pic_offset(x61f861f861f861f8), %mm4 /* 25080-> V120 */
paddsw %mm3, %mm1 /* V115 ; free mm3 */
pmulhw pic_offset(x5a825a825a825a82), %mm2 /* 23170-> V118 */
psllw $2, %mm0 /* t266 */
movq %mm1, (%esi) /* save V115 */
psllw $1, %mm5 /* t268 */
psubsw %mm4, %mm5 /* V122 */
psubsw %mm0, %mm4 /* V121 ; free mm0 */
psllw $1, %mm5 /* t270 */
psubsw %mm1, %mm5 /* V123 ; free mm1 */
psllw $2, %mm2 /* t272 */
psubsw %mm5, %mm2 /* V124 (keep V123) */
psllw $1, %mm4 /* t274 */
movq %mm5, 8*2(%esi) /* save V123 ; free mm5 */
paddsw %mm2, %mm4 /* V125 (keep V124) */
/* column 0: even part (after transpose) */
movq 8*12(%esi), %mm0 /* tmt12 */
movq %mm6, %mm3 /* duplicate tmt4 */
psubsw %mm0, %mm6 /* V100 */
paddsw %mm0, %mm3 /* V101 ; free mm0 */
pmulhw pic_offset(x5a825a825a825a82), %mm6 /* 23170 ->V102 */
movq %mm7, %mm5 /* duplicate tmt0 */
movq 8*8(%esi), %mm1 /* tmt8 */
paddsw %mm1, %mm7 /* V103 */
psubsw %mm1, %mm5 /* V104 ; free mm1 */
movq %mm7, %mm0 /* duplicate V103 */
psllw $2, %mm6 /* t245 */
paddsw %mm3, %mm7 /* V106 */
movq %mm5, %mm1 /* duplicate V104 */
psubsw %mm3, %mm6 /* V105 */
psubsw %mm3, %mm0 /* V109; free mm3 */
paddsw %mm6, %mm5 /* V107 */
psubsw %mm6, %mm1 /* V108 ; free mm6 */
/* column 0: output butterfly (after transform) */
movq %mm1, %mm3 /* duplicate V108 */
paddsw %mm2, %mm1 /* out4 */
psraw $4, %mm1
psubsw %mm2, %mm3 /* out10 ; free mm2 */
psraw $4, %mm3
movq %mm0, %mm6 /* duplicate V109 */
movq %mm1, 8*4(%esi) /* out4 ; free mm1 */
psubsw %mm4, %mm0 /* out6 */
movq %mm3, 8*10(%esi) /* out10 ; free mm3 */
psraw $4, %mm0
paddsw %mm4, %mm6 /* out8 ; free mm4 */
movq %mm7, %mm1 /* duplicate V106 */
movq %mm0, 8*6(%esi) /* out6 ; free mm0 */
psraw $4, %mm6
movq (%esi), %mm4 /* V115 */
movq %mm6, 8*8(%esi) /* out8 ; free mm6 */
movq %mm5, %mm2 /* duplicate V107 */
movq 8*2(%esi), %mm3 /* V123 */
paddsw %mm4, %mm7 /* out0 */
/* moved up from next block */
movq pic_offset(scratch3), %mm0
psraw $4, %mm7
/* moved up from next block */
movq pic_offset(scratch5), %mm6
psubsw %mm4, %mm1 /* out14 ; free mm4 */
paddsw %mm3, %mm5 /* out2 */
psraw $4, %mm1
movq %mm7, (%esi) /* out0 ; free mm7 */
psraw $4, %mm5
movq %mm1, 8*14(%esi) /* out14 ; free mm1 */
psubsw %mm3, %mm2 /* out12 ; free mm3 */
movq %mm5, 8*2(%esi) /* out2 ; free mm5 */
psraw $4, %mm2
/* moved up to the prev block */
movq pic_offset(scratch7), %mm4
/* moved up to the prev block */
psraw $4, %mm0
movq %mm2, 8*12(%esi) /* out12 ; free mm2 */
/* moved up to the prev block */
psraw $4, %mm6
/* move back the data to its correct place
* moved up to the prev block
* movq pic_offset(scratch3), %mm0
* movq pic_offset(scratch5), %mm6
* movq pic_offset(scratch7), %mm4
* psraw $4, %mm0
* psraw $4, %mm6
*/
movq pic_offset(scratch1), %mm1
psraw $4, %mm4
movq %mm0, 8*3(%esi) /* out3 */
psraw $4, %mm1
movq %mm6, 8*5(%esi) /* out5 */
movq %mm4, 8*7(%esi) /* out7 */
movq %mm1, 8(%esi) /* out1 */
emms
popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size gst_idct_mmx_idct,.Lfe1-gst_idct_mmx_idct

View file

@ -1,740 +0,0 @@
.data
.align 4
.type rounder0,@object
rounder0:
.long 65536
.long 65536
.size rounder0,8
.align 4
.type rounder4,@object
rounder4:
.long 1024
.long 1024
.size rounder4,8
.align 4
.type rounder1,@object
rounder1:
.long 3597
.long 3597
.size rounder1,8
.align 4
.type rounder7,@object
rounder7:
.long 512
.long 512
.size rounder7,8
.align 4
.type rounder2,@object
rounder2:
.long 2260
.long 2260
.size rounder2,8
.align 4
.type rounder6,@object
rounder6:
.long 512
.long 512
.size rounder6,8
.align 4
.type rounder3,@object
rounder3:
.long 1203
.long 1203
.size rounder3,8
.align 4
.type rounder5,@object
rounder5:
.long 120
.long 120
.size rounder5,8
.align 2
.type _T1.46,@object
_T1.46:
.value 13036
.value 13036
.value 13036
.value 13036
.align 2
.type _T2.47,@object
_T2.47:
.value 27146
.value 27146
.value 27146
.value 27146
.align 2
.type _T3.48,@object
_T3.48:
.value -21746
.value -21746
.value -21746
.value -21746
.align 2
.type _C4.49,@object
_C4.49:
.value 23170
.value 23170
.value 23170
.value 23170
.local scratch0.50
.comm scratch0.50,8,4
.local scratch1.51
.comm scratch1.51,8,4
.align 2
.type table04.54,@object
table04.54:
.value 16384
.value 21407
.value -16384
.value -21407
.value 16384
.value 8867
.value 16384
.value 8867
.value 22725
.value 19266
.value -22725
.value -12873
.value 12873
.value 4520
.value 19266
.value -4520
.value 16384
.value -8867
.value 16384
.value -8867
.value -16384
.value 21407
.value 16384
.value -21407
.value 12873
.value -22725
.value 19266
.value -22725
.value 4520
.value 19266
.value 4520
.value -12873
.align 2
.type table17.55,@object
table17.55:
.value 22725
.value 29692
.value -22725
.value -29692
.value 22725
.value 12299
.value 22725
.value 12299
.value 31521
.value 26722
.value -31521
.value -17855
.value 17855
.value 6270
.value 26722
.value -6270
.value 22725
.value -12299
.value 22725
.value -12299
.value -22725
.value 29692
.value 22725
.value -29692
.value 17855
.value -31521
.value 26722
.value -31521
.value 6270
.value 26722
.value 6270
.value -17855
.align 2
.type table26.56,@object
table26.56:
.value 21407
.value 27969
.value -21407
.value -27969
.value 21407
.value 11585
.value 21407
.value 11585
.value 29692
.value 25172
.value -29692
.value -16819
.value 16819
.value 5906
.value 25172
.value -5906
.value 21407
.value -11585
.value 21407
.value -11585
.value -21407
.value 27969
.value 21407
.value -27969
.value 16819
.value -29692
.value 25172
.value -29692
.value 5906
.value 25172
.value 5906
.value -16819
.align 2
.type table35.57,@object
table35.57:
.value 19266
.value 25172
.value -19266
.value -25172
.value 19266
.value 10426
.value 19266
.value 10426
.value 26722
.value 22654
.value -26722
.value -15137
.value 15137
.value 5315
.value 22654
.value -5315
.value 19266
.value -10426
.value 19266
.value -10426
.value -19266
.value 25172
.value 19266
.value -25172
.value 15137
.value -26722
.value 22654
.value -26722
.value 5315
.value 22654
.value 5315
.value -15137
.text
.align 4
.globl gst_idct_sse_idct
.type gst_idct_sse_idct,@function
gst_idct_sse_idct:
subl $8,%esp
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
call .L51
.L51:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L51],%ebx
movl 28(%esp),%edx
leal table04.54@GOTOFF(%ebx),%eax
movq (%edx), %mm2
movq 8(%edx), %mm5
movq %mm2, %mm0
movq (%eax), %mm3
movq %mm5, %mm6
movq 8(%eax), %mm4
pmaddwd %mm0, %mm3
pshufw $78, %mm2, %mm2
leal rounder0@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
movq 64(%edx), %mm2
psrad $11, %mm0
movq 72(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, (%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 8(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder4@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
leal table17.55@GOTOFF(%ebx),%eax
movq 16(%edx), %mm2
psrad $11, %mm0
movq 24(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 64(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 72(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder1@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
movq 112(%edx), %mm2
psrad $11, %mm0
movq 120(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 16(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 24(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder7@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
leal table26.56@GOTOFF(%ebx),%eax
movq 32(%edx), %mm2
psrad $11, %mm0
movq 40(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 112(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 120(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder2@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
movq 96(%edx), %mm2
psrad $11, %mm0
movq 104(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 32(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 40(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder6@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
leal table35.57@GOTOFF(%ebx),%eax
movq 48(%edx), %mm2
psrad $11, %mm0
movq 56(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 96(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 104(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder3@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
movq 80(%edx), %mm2
psrad $11, %mm0
movq 88(%edx), %mm5
psrad $11, %mm4
packssdw %mm0, %mm1
movq %mm5, %mm6
packssdw %mm3, %mm4
movq %mm2, %mm0
movq %mm1, 48(%edx)
pshufw $177, %mm4, %mm4
movq (%eax), %mm3
movq %mm4, 56(%edx)
pmaddwd %mm0, %mm3
movq 8(%eax), %mm4
pshufw $78, %mm2, %mm2
leal rounder5@GOTOFF(%ebx),%ecx
movq 16(%eax), %mm1
pmaddwd %mm2, %mm4
pmaddwd 32(%eax), %mm0
pshufw $78, %mm6, %mm6
movq 24(%eax), %mm7
pmaddwd %mm5, %mm1
paddd (%ecx), %mm3
pmaddwd %mm6, %mm7
pmaddwd 40(%eax), %mm2
paddd %mm4, %mm3
pmaddwd 48(%eax), %mm5
movq %mm3, %mm4
pmaddwd 56(%eax), %mm6
paddd %mm7, %mm1
paddd (%ecx), %mm0
psubd %mm1, %mm3
psrad $11, %mm3
paddd %mm4, %mm1
paddd %mm2, %mm0
psrad $11, %mm1
paddd %mm6, %mm5
movq %mm0, %mm4
paddd %mm5, %mm0
psubd %mm5, %mm4
psrad $11, %mm0
psrad $11, %mm4
packssdw %mm0, %mm1
packssdw %mm3, %mm4
movq %mm1, 80(%edx)
pshufw $177, %mm4, %mm4
movq %mm4, 88(%edx)
leal _T1.46@GOTOFF(%ebx),%edi
movq (%edi), %mm0
movq 16(%edx), %mm1
movq %mm0, %mm2
movq 112(%edx), %mm4
pmulhw %mm1, %mm0
leal _T3.48@GOTOFF(%ebx),%esi
movl %esi,16(%esp)
movq (%esi), %mm5
pmulhw %mm4, %mm2
movq 80(%edx), %mm6
movq %mm5, %mm7
movq 48(%edx), %mm3
psubsw %mm4, %mm0
leal _T2.47@GOTOFF(%ebx),%ecx
movq (%ecx), %mm4
pmulhw %mm3, %mm5
paddsw %mm2, %mm1
pmulhw %mm6, %mm7
movq %mm4, %mm2
paddsw %mm3, %mm5
pmulhw 32(%edx), %mm4
paddsw %mm6, %mm7
psubsw %mm6, %mm5
paddsw %mm3, %mm7
movq 96(%edx), %mm3
movq %mm0, %mm6
pmulhw %mm3, %mm2
psubsw %mm5, %mm0
psubsw %mm3, %mm4
paddsw %mm6, %mm5
leal scratch0.50@GOTOFF(%ebx),%esi
movl %esi,20(%esp)
movq %mm0, scratch0.50@GOTOFF(%ebx)
movq %mm1, %mm6
paddsw 32(%edx), %mm2
paddsw %mm7, %mm6
psubsw %mm7, %mm1
movq %mm1, %mm7
movq (%edx), %mm3
paddsw %mm5, %mm1
leal _C4.49@GOTOFF(%ebx),%eax
movq (%eax), %mm0
psubsw %mm5, %mm7
leal scratch1.51@GOTOFF(%ebx),%ebp
movq %mm6, scratch1.51@GOTOFF(%ebx)
pmulhw %mm0, %mm1
movq %mm4, %mm6
pmulhw %mm0, %mm7
movq 64(%edx), %mm5
movq %mm3, %mm0
psubsw %mm5, %mm3
paddsw %mm5, %mm0
paddsw %mm3, %mm4
movq %mm0, %mm5
psubsw %mm6, %mm3
paddsw %mm2, %mm5
paddsw %mm1, %mm1
psubsw %mm2, %mm0
paddsw %mm7, %mm7
movq %mm3, %mm2
movq %mm4, %mm6
paddsw %mm7, %mm3
psraw $6, %mm3
paddsw %mm1, %mm4
psraw $6, %mm4
psubsw %mm1, %mm6
movq (%ebp), %mm1
psubsw %mm7, %mm2
psraw $6, %mm6
movq %mm5, %mm7
movq %mm4, 16(%edx)
psraw $6, %mm2
movq %mm3, 32(%edx)
paddsw %mm1, %mm5
movq (%esi), %mm4
psubsw %mm1, %mm7
psraw $6, %mm5
movq %mm0, %mm3
movq %mm2, 80(%edx)
psubsw %mm4, %mm3
psraw $6, %mm7
paddsw %mm0, %mm4
movq %mm5, (%edx)
psraw $6, %mm3
movq %mm6, 96(%edx)
psraw $6, %mm4
movq %mm7, 112(%edx)
movq %mm3, 64(%edx)
movq %mm4, 48(%edx)
movq (%edi), %mm0
movq 24(%edx), %mm1
movq %mm0, %mm2
movq 120(%edx), %mm4
pmulhw %mm1, %mm0
movl 16(%esp),%esi
movq (%esi), %mm5
pmulhw %mm4, %mm2
movq 88(%edx), %mm6
movq %mm5, %mm7
movq 56(%edx), %mm3
psubsw %mm4, %mm0
movq (%ecx), %mm4
pmulhw %mm3, %mm5
paddsw %mm2, %mm1
pmulhw %mm6, %mm7
movq %mm4, %mm2
paddsw %mm3, %mm5
pmulhw 40(%edx), %mm4
paddsw %mm6, %mm7
psubsw %mm6, %mm5
paddsw %mm3, %mm7
movq 104(%edx), %mm3
movq %mm0, %mm6
pmulhw %mm3, %mm2
psubsw %mm5, %mm0
psubsw %mm3, %mm4
paddsw %mm6, %mm5
movq %mm0, scratch0.50@GOTOFF(%ebx)
movq %mm1, %mm6
paddsw 40(%edx), %mm2
paddsw %mm7, %mm6
psubsw %mm7, %mm1
movq %mm1, %mm7
movq 8(%edx), %mm3
paddsw %mm5, %mm1
movq (%eax), %mm0
psubsw %mm5, %mm7
movq %mm6, scratch1.51@GOTOFF(%ebx)
pmulhw %mm0, %mm1
movq %mm4, %mm6
pmulhw %mm0, %mm7
movq 72(%edx), %mm5
movq %mm3, %mm0
psubsw %mm5, %mm3
paddsw %mm5, %mm0
paddsw %mm3, %mm4
movq %mm0, %mm5
psubsw %mm6, %mm3
paddsw %mm2, %mm5
paddsw %mm1, %mm1
psubsw %mm2, %mm0
paddsw %mm7, %mm7
movq %mm3, %mm2
movq %mm4, %mm6
paddsw %mm7, %mm3
psraw $6, %mm3
paddsw %mm1, %mm4
psraw $6, %mm4
psubsw %mm1, %mm6
movq (%ebp), %mm1
psubsw %mm7, %mm2
psraw $6, %mm6
movq %mm5, %mm7
movq %mm4, 24(%edx)
psraw $6, %mm2
movq %mm3, 40(%edx)
paddsw %mm1, %mm5
movl 20(%esp),%esi
movq (%esi), %mm4
psubsw %mm1, %mm7
psraw $6, %mm5
movq %mm0, %mm3
movq %mm2, 88(%edx)
psubsw %mm4, %mm3
psraw $6, %mm7
paddsw %mm0, %mm4
movq %mm5, 8(%edx)
psraw $6, %mm3
movq %mm6, 104(%edx)
psraw $6, %mm4
movq %mm7, 120(%edx)
movq %mm3, 72(%edx)
movq %mm4, 56(%edx)
popl %ebx
popl %esi
popl %edi
popl %ebp
addl $8,%esp
ret

View file

@ -1,7 +0,0 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

View file

@ -1,13 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstputbits.la
libgstputbits_la_SOURCES = gstputbits.c
libgstputbitsincludedir = $(includedir)/gst/libs/gstputbits
libgstputbitsinclude_HEADERS = gstputbits.h
noinst_HEADERS = gstputbits.h
libgstputbits_la_LIBADD = $(GST_LIBS)
libgstputbits_la_CFLAGS = $(GST_CFLAGS) -funroll-all-loops -finline-functions -ffast-math

View file

@ -1,101 +0,0 @@
/* putbits.c, bit-level output */
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "gstputbits.h"
/* initialize buffer, call once before first putbits or alignbits */
void gst_putbits_init(gst_putbits_t *pb)
{
pb->outcnt = 8;
pb->bytecnt = 0;
pb->outbase = 0;
}
void gst_putbits_new_empty_buffer(gst_putbits_t *pb, int len)
{
pb->outbfr = pb->outbase = malloc(len);
pb->temp = 0;
pb->len = len;
pb->newlen = 0;
pb->outcnt = 8;
}
void gst_putbits_new_buffer(gst_putbits_t *pb, unsigned char *buffer, int len)
{
pb->outbfr = buffer;
pb->temp = 0;
pb->outcnt = 8;
pb->bytecnt = 0;
pb->len = len;
}
/* write rightmost n (0<=n<=32) bits of val to outfile */
void gst_putbits(gst_putbits_t *pb, int val, int n)
{
int i;
unsigned int mask;
//printf("putbits: %p %08x %d %d %d\n", pb, val, n, pb->outcnt, pb->newlen);
mask = 1 << (n-1); /* selects first (leftmost) bit */
for (i=0; i<n; i++)
{
pb->temp <<= 1;
if (val & mask)
pb->temp|= 1;
mask >>= 1; /* select next bit */
pb->outcnt--;
if (pb->outcnt==0) /* 8 bit buffer full */
{
pb->len--;
pb->newlen++;
*(pb->outbfr++) = pb->temp;
pb->outcnt = 8;
pb->bytecnt++;
}
}
}
/* zero bit stuffing to next byte boundary (5.2.3, 6.2.1) */
void gst_putbits_align(gst_putbits_t *pb)
{
if (pb->outcnt!=8)
gst_putbits(pb, 0, pb->outcnt);
}
/* return total number of generated bits */
int gst_putbits_bitcount(gst_putbits_t *pb)
{
return 8*pb->bytecnt + (8-pb->outcnt);
}

View file

@ -1,78 +0,0 @@
/* putbits.h, bit-level output */
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license fee or
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
* any and all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and user's
* customers, employees, agents, transferees, successors, and assigns.
*
* The MPEG Software Simulation Group does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
* are subject to royalty fees to patent holders. Many of these patents are
* general enough such that they are unavoidable regardless of implementation
* design.
*
*/
#ifndef __GST_PUTBITS_H__
#define __GST_PUTBITS_H__
typedef struct _gst_putbits_t gst_putbits_t;
struct _gst_putbits_t {
unsigned char *outbfr;
unsigned char *outbase;
unsigned char temp;
int outcnt;
int bytecnt;
int len;
int newlen;
};
void gst_putbits_init(gst_putbits_t *pb);
void gst_putbits_new_empty_buffer(gst_putbits_t *pb, int len);
void gst_putbits_new_buffer(gst_putbits_t *pb, unsigned char *buffer, int len);
void gst_putbits(gst_putbits_t *pb, int val, int n);
void gst_putbits_align(gst_putbits_t *pb);
int gst_putbits_bitcount(gst_putbits_t *pb);
#define gst_putbits1(gb, val) gst_putbits(gb, val, 1)
#define gst_putbits2(gb, val) gst_putbits(gb, val, 2)
#define gst_putbits3(gb, val) gst_putbits(gb, val, 3)
#define gst_putbits4(gb, val) gst_putbits(gb, val, 4)
#define gst_putbits5(gb, val) gst_putbits(gb, val, 5)
#define gst_putbits6(gb, val) gst_putbits(gb, val, 6)
#define gst_putbits7(gb, val) gst_putbits(gb, val, 7)
#define gst_putbits8(gb, val) gst_putbits(gb, val, 8)
#define gst_putbits9(gb, val) gst_putbits(gb, val, 9)
#define gst_putbits10(gb, val) gst_putbits(gb, val, 10)
#define gst_putbits11(gb, val) gst_putbits(gb, val, 11)
#define gst_putbits12(gb, val) gst_putbits(gb, val, 12)
#define gst_putbits13(gb, val) gst_putbits(gb, val, 13)
#define gst_putbits14(gb, val) gst_putbits(gb, val, 14)
#define gst_putbits15(gb, val) gst_putbits(gb, val, 15)
#define gst_putbits16(gb, val) gst_putbits(gb, val, 16)
#define gst_putbits17(gb, val) gst_putbits(gb, val, 17)
#define gst_putbits18(gb, val) gst_putbits(gb, val, 18)
#define gst_putbits19(gb, val) gst_putbits(gb, val, 19)
#define gst_putbits20(gb, val) gst_putbits(gb, val, 20)
#define gst_putbits21(gb, val) gst_putbits(gb, val, 21)
#define gst_putbits22(gb, val) gst_putbits(gb, val, 22)
#define gst_putbits32(gb, val) gst_putbits(gb, val, 32)
#define gst_putbitsn(gb, val, n) gst_putbits(gb, val, n)
#endif /* __GST_PUTBITS_H__ */

View file

@ -1,29 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libresample.la
libresample_la_SOURCES = dtos.c functable.c resample.c resample.h
noinst_HEADERS = resample.h
#check_PROGRAMS = test
#test_SOURCES = test.c
#test_LDADD = libresample.la
if HAVE_CPU_I386
ARCHCFLAGS = -march=i486
else
if HAVE_CPU_PPC
ARCHCFLAGS = -Wa,-m7400
else
ARCHCFLAGS =
endif
endif
libresample_la_LIBADD = $(GST_LIBS)
libresample_la_CFLAGS = $(GST_CFLAGS) -ffast-math $(ARCHCFLAGS)

View file

@ -1,62 +0,0 @@
This is a snapshot of my current work developing an audio
resampling library. While working on this library, I started
writing lots of general purpose functions that should really
be part of a larger library. Rather than have a constantly
changing library, and since the current code is capable, I
decided to freeze this codebase for use with gstreamer, and
move active development of the code elsewhere.
The algorithm used is based on Shannon's theorem, which says
that you can recreate an input signal from equidistant samples
using a sin(x)/x filter; thus, you can create new samples from
the regenerated input signal. Since sin(x)/x is expensive to
evaluate, an interpolated lookup table is used. Also, a
windowing function (1-x^2)^2 is used, which aids the convergence
of sin(x)/x for lower frequencies at the expense of higher.
There is one tunable parameter, which is the filter length.
Longer filter lengths are obviously slower, but more accurate.
There's not much reason to use a filter length longer than 64,
since other approximations start to dominate. Filter lengths
as short as 8 are audially acceptable, but should not be
considered for serious work.
Performance: A PowerPC G4 at 400 Mhz can resample 2 audio
channels at almost 10x speed with a filter length of 64, without
using Altivec extensions. (My goal was 10x speed, which I almost
reached. Maybe later.)
Limitations: Currently only supports streams in the form of
interleaved signed 16-bit samples.
The test.c program is a simple regression test. It creates a
test input pattern (1 sec at 48 khz) that is a frequency ramp
from 0 to 24000 hz, and then converts it to 44100 hz using a
filter length of 64. It then compares the result to the same
pattern generated at 44100 hz, and outputs the result to the
file "out".
A graph of the correct output should have field 2 and field 4
almost equal (plus/minus 1) up to about sample 40000 (which
corresponds to 20 khz), and then field 2 should be close to 0
above that. Running the test program will print to stdout
something like the following:
time 0.112526
average error 10k=0.4105 22k=639.34
The average error is RMS error over the range [0-10khz] and
[0-22khz], and is expressed in sample values, for an input
amplitude of 16000. Note that RMS errors below 1.0 can't
really be compared, but basically this shows that below
10 khz, the resampler is nearly perfect. Most of the error
is concentrated above 20 khz.
If the average error is significantly larger after modifying
the code, it's probably not good.
dave...

View file

@ -1,201 +0,0 @@
/* Resampling library
* Copyright (C) <2001> David A. Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or 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 <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//#include <ml.h>
#include <resample.h>
#define short_to_double_table
//#define short_to_double_altivec
#define short_to_double_unroll
#ifdef short_to_double_table
static float ints_high[256];
static float ints_low[256];
void conv_double_short_table(double *dest, short *src, int n)
{
static int init = 0;
int i;
unsigned int idx;
if(!init){
for(i=0;i<256;i++){
ints_high[i]=256.0*((i<128)?i:i-256);
ints_low[i]=i;
}
init = 1;
}
if(n&1){
idx = (unsigned short)*src++;
*dest++ = ints_high[(idx>>8)] + ints_low[(idx&0xff)];
n-=1;
}
for(i=0;i<n;i+=2){
idx = (unsigned short)*src++;
*dest++ = ints_high[(idx>>8)] + ints_low[(idx&0xff)];
idx = (unsigned short)*src++;
*dest++ = ints_high[(idx>>8)] + ints_low[(idx&0xff)];
}
}
#endif
#ifdef short_to_double_unroll
void conv_double_short_unroll(double *dest, short *src, int n)
{
if(n&1){
*dest++ = *src++;
n--;
}
if(n&2){
*dest++ = *src++;
*dest++ = *src++;
n-=2;
}
while(n>0){
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
*dest++ = *src++;
n-=4;
}
}
#endif
void conv_double_short_ref(double *dest, short *src, int n)
{
int i;
for(i=0;i<n;i++){
dest[i]=src[i];
}
}
#ifdef HAVE_CPU_PPC
#if 0
static union { int i[4]; float f[4]; } av_tmp __attribute__ ((__aligned__ (16)));
void conv_double_short_altivec(double *dest, short *src, int n)
{
int i;
for(i=0;i<n;i+=4){
av_tmp.i[0] = src[0];
av_tmp.i[1] = src[1];
av_tmp.i[2] = src[2];
av_tmp.i[3] = src[3];
asm(
" lvx 0,0,%0\n"
" vcfsx 1,0,0\n"
" stvx 1,0,%0\n"
: : "r" (&av_tmp)
);
dest[0]=av_tmp.f[0];
dest[1]=av_tmp.f[1];
dest[2]=av_tmp.f[2];
dest[3]=av_tmp.f[3];
src += 4;
dest += 4;
}
}
#endif
#endif
/* double to short */
void conv_short_double_ref(short *dest, double *src, int n)
{
int i;
double x;
for(i=0;i<n;i++){
x = *src++;
if(x<-32768.0)x=-32768.0;
if(x>32767.0)x=32767.0;
*dest++ = rint(x);
}
}
#ifdef HAVE_CPU_PPC
void conv_short_double_ppcasm(short *dest, double *src, int n)
{
int tmp[2];
double min = -32768.0;
double max = 32767.0;
double ftmp0, ftmp1;
asm __volatile__(
"\taddic. %3,%3,-8\n"
"\taddic. %6,%6,-2\n"
"loop:\n"
"\tlfdu %0,8(%3)\n"
"\tfsub %1,%0,%4\n"
"\tfsel %0,%1,%0,%4\n"
"\tfsub %1,%0,%5\n"
"\tfsel %0,%1,%5,%0\n"
"\tfctiw %1,%0\n"
"\taddic. 5,5,-1\n"
"\tstfd %1,0(%2)\n"
"\tlhz 9,6(%2)\n"
"\tsthu 9,2(%6)\n"
"\tbne loop\n"
: "=&f" (ftmp0), "=&f" (ftmp1)
: "b" (tmp), "r" (src), "f" (min), "f" (max), "r" (dest)
: "r9", "r5" );
}
#endif
void conv_double_short_dstr(double *dest, short *src, int n, int dstr)
{
int i;
void *d = dest;
for(i=0;i<n;i++){
(*(double *)d)=*src++;
d += dstr;
}
}
void conv_short_double_sstr(short *dest, double *src, int n, int sstr)
{
int i;
double x;
void *s = src;
for(i=0;i<n;i++){
x = *(double *)s;
if(x<-32768.0)x=-32768.0;
if(x>32767.0)x=32767.0;
*dest++ = rint(x);
s += sstr;
}
}

View file

@ -1,311 +0,0 @@
/* Resampling library
* Copyright (C) <2001> David A. Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or 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 <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <resample.h>
double functable_sinc(void *p,double x)
{
if(x==0)return 1;
return sin(x)/x;
}
double functable_dsinc(void *p,double x)
{
if(x==0)return 0;
return cos(x)/x - sin(x)/(x*x);
}
double functable_window_boxcar(void *p,double x)
{
if(x<-1 || x>1)return 0;
return 1;
}
double functable_window_dboxcar(void *p,double x)
{
return 0;
}
double functable_window_std(void *p,double x)
{
if(x<-1 || x>1)return 0;
return (1-x*x)*(1-x*x);
}
double functable_window_dstd(void *p,double x)
{
if(x<-1 || x>1)return 0;
return -4*x*(1-x*x);
}
void functable_init(functable_t *t)
{
int i;
double x;
t->fx = malloc(sizeof(double)*(t->len+1));
t->fdx = malloc(sizeof(double)*(t->len+1));
t->invoffset = 1.0 / t->offset;
for(i=0;i<t->len+1;i++){
x = t->start + t->offset * i;
x *= t->scale;
t->fx[i] = t->func_x(t->priv,x);
t->fdx[i] = t->scale * t->func_dx(t->priv,x);
}
if(t->func2_x){
double f1x,f1dx;
double f2x,f2dx;
for(i=0;i<t->len+1;i++){
x = t->start + t->offset * i;
x *= t->scale2;
f2x = t->func2_x(t->priv,x);
f2dx = t->scale2 * t->func2_dx(t->priv,x);
f1x = t->fx[i];
f1dx = t->fdx[i];
t->fx[i] = f1x * f2x;
t->fdx[i] = f1x * f2dx + f1dx * f2x;
}
}
}
double functable_eval(functable_t *t,double x)
{
int i;
double f0, f1, w0, w1;
double x2, x3;
double w;
if(x<t->start || x>(t->start+(t->len+1)*t->offset)){
printf("x out of range %g\n",x);
}
x -= t->start;
x /= t->offset;
i = floor(x);
x -= i;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = (x - 2 * x2 + x3) * t->offset;
w1 = (-x2 + x3) * t->offset;
//printf("i=%d x=%g f0=%g f1=%g w0=%g w1=%g\n",i,x,f0,f1,w0,w1);
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
//w = t->fx[i] * (1-x) + t->fx[i+1] * x;
return w;
}
double functable_fir(functable_t *t, double x, int n, double *data, int len)
{
int i,j;
double f0, f1, w0, w1;
double x2, x3;
double w;
double sum;
x -= t->start;
x /= t->offset;
i = floor(x);
x -= i;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = (x - 2 * x2 + x3) * t->offset;
w1 = (-x2 + x3) * t->offset;
sum = 0;
for(j=0;j<len;j++){
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
sum += data[j*2] * w;
i += n;
}
return sum;
}
void functable_fir2(functable_t *t, double *r0, double *r1, double x,
int n, double *data, int len)
{
int i,j;
double f0, f1, w0, w1;
double x2, x3;
double w;
double sum0, sum1;
double floor_x;
x -= t->start;
x *= t->invoffset;
floor_x = floor(x);
i = floor_x;
x -= floor_x;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = (x - 2 * x2 + x3) * t->offset;
w1 = (-x2 + x3) * t->offset;
sum0 = 0;
sum1 = 0;
for(j=0;j<len;j++){
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
sum0 += data[j*2] * w;
sum1 += data[j*2+1] * w;
i += n;
#define unroll2
#define unroll3
#define unroll4
#ifdef unroll2
j++;
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
sum0 += data[j*2] * w;
sum1 += data[j*2+1] * w;
i += n;
#endif
#ifdef unroll3
j++;
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
sum0 += data[j*2] * w;
sum1 += data[j*2+1] * w;
i += n;
#endif
#ifdef unroll4
j++;
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
sum0 += data[j*2] * w;
sum1 += data[j*2+1] * w;
i += n;
#endif
}
*r0 = sum0;
*r1 = sum1;
}
#ifdef unused
void functable_fir2_altivec(functable_t *t, float *r0, float *r1,
double x, int n, float *data, int len)
{
int i,j;
double f0, f1, w0, w1;
double x2, x3;
double w;
double sum0, sum1;
double floor_x;
x -= t->start;
x *= t->invoffset;
floor_x = floor(x);
i = floor_x;
x -= floor_x;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = (x - 2 * x2 + x3) * t->offset;
w1 = (-x2 + x3) * t->offset;
sum0 = 0;
sum1 = 0;
for(j=0;j<len;j++){
// t->fx, t->fdx needs to be multiplexed by n
// we need 5 consecutive floats, which fit into 2 vecs
// load v0, t->fx[i]
// load v1, t->fx[i+n]
// v2 = v0 (not correct)
// v3 = (v0>>32) || (v1<<3*32) (not correct)
//
// load v4, t->dfx[i]
// load v5, t->dfx[i+n]
// v6 = v4 (not correct)
// v7 = (v4>>32) || (v5<<3*32) (not correct)
//
// v8 = splat(f0)
// v9 = splat(f1)
// v10 = splat(w0)
// v11 = splat(w1)
//
// v12 = v2 * v8
// v12 += v3 * v9
// v12 += v6 * v10
// v12 += v7 * v11
w = t->fx[i] * f0 + t->fx[i + 1] * f1 +
t->fdx[i] * w0 + t->fdx[i + 1] * w1;
// v13 = data[j*2]
// v14 = data[j*2+4]
// v15 = deinterlace_high(v13,v14)
// v16 = deinterlace_low(v13,v14)
// (sum0) v17 += multsum(v13,v15)
// (sum1) v18 += multsum(v14,v16)
sum0 += data[j*2] * w;
sum1 += data[j*2+1] * w;
i += n;
}
*r0 = sum0;
*r1 = sum1;
}
#endif

View file

@ -1,530 +0,0 @@
/* Resampling library
* Copyright (C) <2001> David A. Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or 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 <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <resample.h>
inline double sinc(double x)
{
if(x==0)return 1;
return sin(x) / x;
}
inline double window_func(double x)
{
x = 1 - x*x;
return x*x;
}
signed short double_to_s16(double x)
{
if(x<-32768){
printf("clipped\n");
return -32768;
}
if(x>32767){
printf("clipped\n");
return -32767;
}
return rint(x);
}
signed short double_to_s16_ppcasm(double x)
{
if(x<-32768){
return -32768;
}
if(x>32767){
return -32767;
}
return rint(x);
}
static void resample_sinc_ft(resample_t * r);
void resample_init(resample_t * r)
{
r->i_start = 0;
if(r->filter_length&1){
r->o_start = 0;
}else{
r->o_start = r->o_inc * 0.5;
}
memset(r->acc, 0, sizeof(r->acc));
resample_reinit(r);
}
void resample_reinit(resample_t * r)
{
/* i_inc is the number of samples that the output increments for
* each input sample. o_inc is the opposite. */
r->i_inc = (double) r->o_rate / r->i_rate;
r->o_inc = (double) r->i_rate / r->o_rate;
r->halftaps = (r->filter_length - 1.0) * 0.5;
switch (r->method) {
default:
case RESAMPLE_NEAREST:
r->scale = resample_nearest;
break;
case RESAMPLE_BILINEAR:
r->scale = resample_bilinear;
break;
case RESAMPLE_SINC_SLOW:
r->scale = resample_sinc;
break;
case RESAMPLE_SINC:
r->scale = resample_sinc_ft;
break;
}
}
/*
* Prepare to be confused.
*
* We keep a "timebase" that is based on output samples. The zero
* of the timebase cooresponds to the next output sample that will
* be written.
*
* i_start is the "time" that corresponds to the first input sample
* in an incoming buffer. Since the output depends on input samples
* ahead in time, i_start will tend to be around halftaps.
*
* i_start_buf is the time of the first sample in the temporary
* buffer.
*/
void resample_scale(resample_t * r, void *i_buf, unsigned int i_size)
{
int o_size;
r->i_buf = i_buf;
r->i_samples = i_size / 2 / r->channels;
r->i_start_buf = r->i_start - r->filter_length * r->i_inc;
/* i_start is the offset (in a given output sample) that is the
* beginning of the current input buffer */
r->i_end = r->i_start + r->i_inc * r->i_samples;
r->o_samples = floor(r->i_end - r->halftaps * r->i_inc);
o_size = r->o_samples * r->channels * 2;
r->o_buf = r->get_buffer(r->priv, o_size);
if(r->verbose){
printf("resample_scale: i_buf=%p i_size=%d\n",
i_buf,i_size);
printf("resample_scale: i_samples=%d o_samples=%d i_inc=%g o_buf=%p\n",
r->i_samples, r->o_samples, r->i_inc, r->o_buf);
printf("resample_scale: i_start=%g i_end=%g o_start=%g\n",
r->i_start, r->i_end, r->o_start);
}
if ((r->filter_length + r->i_samples)*2*2 > r->buffer_len) {
int size = (r->filter_length + r->i_samples) * sizeof(double) * 2;
if(r->verbose){
printf("resample temp buffer size=%d\n",size);
}
if(r->buffer)free(r->buffer);
r->buffer_len = size;
r->buffer = malloc(size);
memset(r->buffer, 0, size);
}
if(r->channels==2){
conv_double_short(
r->buffer + r->filter_length * sizeof(double) * 2,
r->i_buf, r->i_samples * 2);
}else{
conv_double_short_dstr(
r->buffer + r->filter_length * sizeof(double) * 2,
r->i_buf, r->i_samples, sizeof(double) * 2);
}
r->scale(r);
memcpy(r->buffer,
r->buffer + r->i_samples * sizeof(double) * 2,
r->filter_length * sizeof(double) * 2);
/* updating times */
r->i_start += r->i_samples * r->i_inc;
r->o_start += r->o_samples * r->o_inc - r->i_samples;
/* adjusting timebase zero */
r->i_start -= r->o_samples;
}
void resample_nearest(resample_t * r)
{
signed short *i_ptr, *o_ptr;
int i_count = 0;
double a;
int i;
i_ptr = (signed short *) r->i_buf;
o_ptr = (signed short *) r->o_buf;
a = r->o_start;
i_count = 0;
#define SCALE_LOOP(COPY,INC) \
for (i = 0; i < r->o_samples; i++) { \
COPY; \
a += r->o_inc; \
while (a >= 1) { \
a -= 1; \
i_ptr+=INC; \
i_count++; \
} \
o_ptr+=INC; \
}
switch (r->channels) {
case 1:
SCALE_LOOP(o_ptr[0] = i_ptr[0], 1);
break;
case 2:
SCALE_LOOP(o_ptr[0] = i_ptr[0];
o_ptr[1] = i_ptr[1], 2);
break;
default:
{
int n, n_chan = r->channels;
SCALE_LOOP(for (n = 0; n < n_chan; n++) o_ptr[n] =
i_ptr[n], n_chan);
}
}
if (i_count != r->i_samples) {
printf("handled %d in samples (expected %d)\n", i_count,
r->i_samples);
}
}
void resample_bilinear(resample_t * r)
{
signed short *i_ptr, *o_ptr;
int o_count = 0;
double b;
int i;
double acc0, acc1;
i_ptr = (signed short *) r->i_buf;
o_ptr = (signed short *) r->o_buf;
acc0 = r->acc[0];
acc1 = r->acc[1];
b = r->i_start;
for (i = 0; i < r->i_samples; i++) {
b += r->i_inc;
//printf("in %d\n",i_ptr[0]);
if(b>=2){
printf("not expecting b>=2\n");
}
if (b >= 1) {
acc0 += (1.0 - (b-r->i_inc)) * i_ptr[0];
acc1 += (1.0 - (b-r->i_inc)) * i_ptr[1];
o_ptr[0] = rint(acc0);
//printf("out %d\n",o_ptr[0]);
o_ptr[1] = rint(acc1);
o_ptr += 2;
o_count++;
b -= 1.0;
acc0 = b * i_ptr[0];
acc1 = b * i_ptr[1];
} else {
acc0 += i_ptr[0] * r->i_inc;
acc1 += i_ptr[1] * r->i_inc;
}
i_ptr += 2;
}
r->acc[0] = acc0;
r->acc[1] = acc1;
if (o_count != r->o_samples) {
printf("handled %d out samples (expected %d)\n", o_count,
r->o_samples);
}
}
void resample_sinc_slow(resample_t * r)
{
signed short *i_ptr, *o_ptr;
int i, j;
double c0, c1;
double a;
int start;
double center;
double weight;
if (!r->buffer) {
int size = r->filter_length * 2 * r->channels;
printf("resample temp buffer\n");
r->buffer = malloc(size);
memset(r->buffer, 0, size);
}
i_ptr = (signed short *) r->i_buf;
o_ptr = (signed short *) r->o_buf;
a = r->i_start;
#define GETBUF(index,chan) (((index)<0) \
? ((short *)(r->buffer))[((index)+r->filter_length)*2+(chan)] \
: i_ptr[(index)*2+(chan)])
{
double sinx, cosx, sind, cosd;
double x, d;
double t;
for (i = 0; i < r->o_samples; i++) {
start = floor(a) - r->filter_length;
center = a - r->halftaps;
x = M_PI * (start - center) * r->o_inc;
sinx = sin(M_PI * (start - center) * r->o_inc);
cosx = cos(M_PI * (start - center) * r->o_inc);
d = M_PI * r->o_inc;
sind = sin(M_PI * r->o_inc);
cosd = cos(M_PI * r->o_inc);
c0 = 0;
c1 = 0;
for (j = 0; j < r->filter_length; j++) {
weight = (x==0)?1:(sinx/x);
//printf("j %d sin %g cos %g\n",j,sinx,cosx);
//printf("j %d sin %g x %g sinc %g\n",j,sinx,x,weight);
c0 += weight * GETBUF((start + j), 0);
c1 += weight * GETBUF((start + j), 1);
t = cosx * cosd - sinx * sind;
sinx = cosx * sind + sinx * cosd;
cosx = t;
x += d;
}
o_ptr[0] = rint(c0);
o_ptr[1] = rint(c1);
o_ptr += 2;
a += r->o_inc;
}
}
memcpy(r->buffer,
i_ptr + (r->i_samples - r->filter_length) * r->channels,
r->filter_length * 2 * r->channels);
}
void resample_sinc(resample_t * r)
{
double *ptr;
signed short *o_ptr;
int i, j;
double c0, c1;
double a;
int start;
double center;
double weight;
double x0, x, d;
double scale;
ptr = (double *) r->buffer;
o_ptr = (signed short *) r->o_buf;
/* scale provides a cutoff frequency for the low
* pass filter aspects of sinc(). scale=M_PI
* will cut off at the input frequency, which is
* good for up-sampling, but will cause aliasing
* for downsampling. Downsampling needs to be
* cut off at o_rate, thus scale=M_PI*r->i_inc. */
/* actually, it needs to be M_PI*r->i_inc*r->i_inc.
* Need to research why. */
scale = M_PI*r->i_inc;
for (i = 0; i < r->o_samples; i++) {
a = r->o_start + i * r->o_inc;
start = floor(a - r->halftaps);
//printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1);
center = a;
//x = M_PI * (start - center) * r->o_inc;
//d = M_PI * r->o_inc;
//x = (start - center) * r->o_inc;
x0 = (start - center) * r->o_inc;
d = r->o_inc;
c0 = 0;
c1 = 0;
for (j = 0; j < r->filter_length; j++) {
x = x0 + d * j;
weight = sinc(x*scale*r->i_inc)*scale/M_PI;
weight *= window_func(x/r->halftaps*r->i_inc);
c0 += weight * ptr[(start + j + r->filter_length)*2 + 0];
c1 += weight * ptr[(start + j + r->filter_length)*2 + 1];
}
o_ptr[0] = double_to_s16(c0);
o_ptr[1] = double_to_s16(c1);
o_ptr += 2;
}
}
/*
* Resampling audio is best done using a sinc() filter.
*
*
* out[t] = Sum( in[t'] * sinc((t-t')/delta_t), all t')
*
* The immediate problem with this algorithm is that it involves a
* sum over an infinite number of input samples, both in the past
* and future. Note that even though sinc(x) is bounded by 1/x,
* and thus decays to 0 for large x, since sum(x,{x=0,1..,n}) diverges
* as log(n), we need to be careful about convergence. This is
* typically done by using a windowing function, which also makes
* the sum over a finite number of input samples.
*
* The next problem is computational: sinc(), and especially
* sinc() multiplied by a non-trivial windowing function is expensive
* to calculate, and also difficult to find SIMD optimizations. Since
* the time increment on input and output is different, it is not
* possible to use a FIR filter, because the taps would have to be
* recalculated for every t.
*
* To get around the expense of calculating sinc() for every point,
* we pre-calculate sinc() at a number of points, and then interpolate
* for the values we want in calculations. The interpolation method
* chosen is bi-cubic, which requires both the evalated function and
* its derivative at every pre-sampled point. Also, if the sampled
* points are spaced commensurate with the input delta_t, we notice
* that the interpolating weights are the same for every input point.
* This decreases the number of operations to 4 multiplies and 4 adds
* for each tap, regardless of the complexity of the filtering function.
*
* At this point, it is possible to rearrange the problem as the sum
* of 4 properly weghted FIR filters. Typical SIMD computation units
* are highly optimized for FIR filters, making long filter lengths
* reasonable.
*/
static functable_t *ft;
double out_tmp[10000];
static void resample_sinc_ft(resample_t * r)
{
double *ptr;
signed short *o_ptr;
int i;
//int j;
double c0, c1;
//double a;
double start_f, start_x;
int start;
double center;
//double weight;
double x, d;
double scale;
int n = 4;
scale = r->i_inc; // cutoff at 22050
//scale = 1.0; // cutoff at 24000
//scale = r->i_inc * 0.5; // cutoff at 11025
if(!ft){
ft = malloc(sizeof(*ft));
memset(ft,0,sizeof(*ft));
ft->len = (r->filter_length + 2) * n;
ft->offset = 1.0 / n;
ft->start = - ft->len * 0.5 * ft->offset;
ft->func_x = functable_sinc;
ft->func_dx = functable_dsinc;
ft->scale = M_PI * scale;
ft->func2_x = functable_window_std;
ft->func2_dx = functable_window_dstd;
ft->scale2 = 1.0 / r->halftaps;
functable_init(ft);
//printf("len=%d offset=%g start=%g\n",ft->len,ft->offset,ft->start);
}
ptr = r->buffer;
o_ptr = (signed short *) r->o_buf;
center = r->o_start;
start_x = center - r->halftaps;
start_f = floor(start_x);
start_x -= start_f;
start = start_f;
for (i = 0; i < r->o_samples; i++) {
//start_f = floor(center - r->halftaps);
//printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1);
x = start_f - center;
d = 1;
c0 = 0;
c1 = 0;
//#define slow
#ifdef slow
for (j = 0; j < r->filter_length; j++) {
weight = functable_eval(ft,x)*scale;
//weight = sinc(M_PI * scale * x)*scale*r->i_inc;
//weight *= window_func(x / r->halftaps);
c0 += weight * ptr[(start + j + r->filter_length)*2 + 0];
c1 += weight * ptr[(start + j + r->filter_length)*2 + 1];
x += d;
}
#else
functable_fir2(ft,
&c0,&c1,
x, n,
ptr+(start + r->filter_length)*2,
r->filter_length);
c0 *= scale;
c1 *= scale;
#endif
out_tmp[2 * i + 0] = c0;
out_tmp[2 * i + 1] = c1;
center += r->o_inc;
start_x += r->o_inc;
while(start_x>=1.0){
start_f++;
start_x -= 1.0;
start++;
}
}
if(r->channels==2){
conv_short_double(r->o_buf,out_tmp,2 * r->o_samples);
}else{
conv_short_double_sstr(r->o_buf,out_tmp,r->o_samples,2 * sizeof(double));
}
}

View file

@ -1,159 +0,0 @@
/* Resampling library
* Copyright (C) <2001> David Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or 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 __RESAMPLE_H__
#define __RESAMPLE_H__
#include <config.h>
typedef struct resample_s resample_t;
struct resample_s {
/* parameters */
int method;
int channels;
int verbose;
int filter_length;
double i_rate;
double o_rate;
void *priv;
void *(*get_buffer)(void *priv, unsigned int size);
/* internal parameters */
double halftaps;
/* filter state */
void *buffer;
int buffer_len;
double i_start;
double o_start;
double i_start_buf;
double i_end_buf;
double i_inc;
double o_inc;
double i_end;
double o_end;
int i_samples;
int o_samples;
void *i_buf, *o_buf;
double acc[10];
/* methods */
void (*scale)(resample_t *r);
double ack;
};
enum{
RESAMPLE_NEAREST = 0,
RESAMPLE_BILINEAR,
RESAMPLE_SINC_SLOW,
RESAMPLE_SINC,
};
void resample_init(resample_t *r);
void resample_reinit(resample_t *r);
void resample_scale(resample_t *r, void *i_buf, unsigned int size);
void resample_nearest(resample_t *r);
void resample_bilinear(resample_t *r);
void resample_sinc(resample_t *r);
void resample_sinc_slow(resample_t *r);
typedef struct functable_s functable_t;
struct functable_s {
double start;
double offset;
int len;
double invoffset;
double scale;
double scale2;
double (*func_x)(void *,double x);
double (*func_dx)(void *,double x);
double (*func2_x)(void *,double x);
double (*func2_dx)(void *,double x);
double *fx;
double *fdx;
void *priv;
};
void functable_init(functable_t *t);
double functable_eval(functable_t *t,double x);
double functable_fir(functable_t *t,double x0,int n,double *data,int len);
void functable_fir2(functable_t *t,double *r0, double *r1, double x0,
int n,double *data,int len);
double functable_sinc(void *p, double x);
double functable_dsinc(void *p, double x);
double functable_window_std(void *p, double x);
double functable_window_dstd(void *p, double x);
double functable_window_boxcar(void *p, double x);
double functable_window_dboxcar(void *p, double x);
/* math lib stuff */
void conv_double_short_table(double *dest, short *src, int n);
void conv_double_short_unroll(double *dest, short *src, int n);
void conv_double_short_ref(double *dest, short *src, int n);
#ifdef HAVE_CPU_PPC
void conv_double_short_altivec(double *dest, short *src, int n);
#endif
void conv_short_double_ref(short *dest, double *src, int n);
#ifdef HAVE_CPU_PPC
void conv_short_double_ppcasm(short *dest, double *src, int n);
#endif
#ifdef HAVE_CPU_PPC
#define conv_double_short conv_double_short_table
#define conv_short_double conv_short_double_ppcasm
#else
#define conv_double_short conv_double_short_ref
#define conv_short_double conv_short_double_ref
#endif
void conv_double_short_dstr(double *dest, short *src, int n, int dstr);
void conv_short_double_sstr(short *dest, double *src, int n, int dstr);
#endif /* __RESAMPLE_H__ */

View file

@ -1,352 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <resample.h>
#define AMP 16000
#define I_RATE 48000
#define O_RATE 44100
//#define O_RATE 24000
//#define test_func(x) 1
//#define test_func(x) sin(2*M_PI*(x)*10)
//#define test_func(x) sin(2*M_PI*(x)*(x)*1000)
#define test_func(x) sin(2*M_PI*(x)*(x)*12000)
short i_buf[I_RATE*2*2];
short o_buf[O_RATE*2*2];
static int i_offset;
static int o_offset;
FILE *out;
void test_res1(void);
void test_res2(void);
void test_res3(void);
void test_res4(void);
void test_res5(void);
void test_res6(void);
void test_res7(void);
int main(int argc,char *argv[])
{
out = fopen("out","w");
test_res7();
return 0;
}
void *get_buffer(void *priv, unsigned int size)
{
void *ret;
ret = ((void *)o_buf) + o_offset;
o_offset += size;
return ret;
}
struct timeval start_time;
void start_timer(void)
{
gettimeofday(&start_time,NULL);
//printf("start %ld.%06ld\n",start_time.tv_sec,start_time.tv_usec);
}
void end_timer(void)
{
struct timeval end_time;
double diff;
gettimeofday(&end_time,NULL);
//printf("end %ld.%06ld\n",end_time.tv_sec,end_time.tv_usec);
diff = (end_time.tv_sec - start_time.tv_sec) +
1e-6*(end_time.tv_usec - start_time.tv_usec);
printf("time %g\n",diff);
}
void test_res1(void)
{
resample_t *r;
int i;
double sum10k,sum22k;
double f;
int n10k,n22k;
double x;
for(i=0;i<I_RATE;i++){
i_buf[i*2+0] = rint(AMP * test_func((double)i/I_RATE));
//i_buf[i*2+1] = rint(AMP * test_func((double)i/I_RATE));
i_buf[i*2+1] = (i<1000)?AMP:0;
}
r = malloc(sizeof(resample_t));
memset(r,0,sizeof(resample_t));
r->i_rate = I_RATE;
r->o_rate = O_RATE;
//r->method = RESAMPLE_SINC_SLOW;
r->method = RESAMPLE_SINC;
r->channels = 2;
//r->verbose = 1;
r->filter_length = 64;
r->get_buffer = get_buffer;
resample_init(r);
start_timer();
#define blocked
#ifdef blocked
for(i=0;i+256<I_RATE;i+=256){
resample_scale(r,i_buf+i*2,256*2*2);
}
if(I_RATE-i){
resample_scale(r,i_buf+i*2,(I_RATE-i)*2*2);
}
#else
resample_scale(r,i_buf,I_RATE*2*2);
#endif
end_timer();
for(i=0;i<O_RATE;i++){
f = AMP*test_func((double)i/O_RATE);
//f = rint(AMP*test_func((double)i/O_RATE));
fprintf(out,"%d %d %d %g %g\n",i,
o_buf[2*i+0],o_buf[2*i+1],
f,o_buf[2*i+0]-f);
}
sum10k=0;
sum22k=0;
n10k=0;
n22k=0;
for(i=0;i<O_RATE;i++){
f = AMP*test_func((double)i/O_RATE);
//f = rint(AMP*test_func((double)i/O_RATE));
x = o_buf[2*i+0]-f;
if(((0.5*i)/O_RATE*I_RATE)<10000){
sum10k += x*x;
n10k++;
}
if(((0.5*i)/O_RATE*I_RATE)<22050){
sum22k += x*x;
n22k++;
}
}
printf("average error 10k=%g 22k=%g\n",
sqrt(sum10k/n10k),
sqrt(sum22k/n22k));
}
void test_res2(void)
{
functable_t *t;
int i;
double x;
double f1,f2;
t = malloc(sizeof(*t));
memset(t,0,sizeof(*t));
t->start = -50.0;
t->offset = 1;
t->len = 100;
t->func_x = functable_sinc;
t->func_dx = functable_dsinc;
functable_init(t);
for(i=0;i<1000;i++){
x = -50.0 + 0.1 * i;
f1 = functable_sinc(NULL,x);
f2 = functable_eval(t,x);
fprintf(out,"%d %g %g %g\n",i,f1,f2,f1-f2);
}
}
void test_res3(void)
{
functable_t *t;
int i;
double x;
double f1,f2;
int n = 1;
t = malloc(sizeof(*t));
memset(t,0,sizeof(*t));
t->start = -50.0;
t->offset = 1.0 / n;
t->len = 100 * n;
t->func_x = functable_sinc;
t->func_dx = functable_dsinc;
t->func2_x = functable_window_std;
t->func2_dx = functable_window_dstd;
t->scale = 1.0;
t->scale2 = 1.0 / (M_PI * 16);
functable_init(t);
for(i=0;i<1000 * n;i++){
x = -50.0 + 0.1/n * i;
f1 = functable_sinc(NULL,t->scale * x) *
functable_window_std(NULL,t->scale2 * x);
f2 = functable_eval(t,x);
fprintf(out,"%d %g %g %g\n",i,f1,f2,f2-f1);
}
}
double sinc_poly(double x)
{
#define INV3FAC 1.66666666666666666e-1
#define INV5FAC 8.33333333333333333e-3
#define INV7FAC 1.984126984e-4
#define INV9FAC 2.755731922e-6
#define INV11FAC 2.505210839e-8
double x2 = x * x;
return 1
- x2 * INV3FAC
+ x2 * x2 * INV5FAC
- x2 * x2 * x2 * INV7FAC;
//+ x2 * x2 * x2 * x2 * INV9FAC
//- x2 * x2 * x2 * x2 * x2 * INV11FAC;
}
void test_res4(void)
{
int i;
double x,f1,f2;
for(i=1;i<100;i++){
x = 0.01 * i;
f1 = 1 - sin(x)/x;
f2 = 1 - sinc_poly(x);
fprintf(out,"%g %.20g %.20g %.20g\n",x,f1,f2,f2-f1);
}
}
void test_res5(void)
{
int i;
double sum;
start_timer();
sum = 0;
for(i=0;i<I_RATE;i++){
sum += i_buf[i*2];
}
end_timer();
i_buf[0] = sum;
}
void short_to_double(double *d,short *x) { *d = *x; }
void short_to_float(float *f,short *x) { *f = *x; }
void float_to_double(double *f,float *x) { *f = *x; }
void double_to_short(short *f,double *x) { *f = *x; }
double res6_tmp[1000];
void test_res6(void)
{
int i;
for(i=0;i<I_RATE;i++){
i_buf[i] = rint(AMP * test_func((double)i/I_RATE));
}
conv_double_short_ref(res6_tmp,i_buf,1000);
for(i=0;i<1000;i++){
res6_tmp[i] *= 3.0;
}
conv_short_double_ppcasm(o_buf,res6_tmp,1000);
for(i=0;i<1000;i++){
fprintf(out,"%d %d %g %d\n",i,i_buf[i],res6_tmp[i],o_buf[i]);
}
}
void test_res7(void)
{
resample_t *r;
int i;
double sum10k,sum22k;
double f;
int n10k,n22k;
double x;
for(i=0;i<I_RATE;i++){
i_buf[i] = rint(AMP * test_func((double)i/I_RATE));
}
r = malloc(sizeof(resample_t));
memset(r,0,sizeof(resample_t));
r->i_rate = I_RATE;
r->o_rate = O_RATE;
//r->method = RESAMPLE_SINC_SLOW;
r->method = RESAMPLE_SINC;
r->channels = 1;
//r->verbose = 1;
r->filter_length = 64;
r->get_buffer = get_buffer;
resample_init(r);
start_timer();
#define blocked
#ifdef blocked
for(i=0;i+256<I_RATE;i+=256){
resample_scale(r,i_buf+i,256*2);
}
if(I_RATE-i){
resample_scale(r,i_buf+i,(I_RATE-i)*2);
}
#else
resample_scale(r,i_buf,I_RATE*2);
#endif
end_timer();
for(i=0;i<O_RATE;i++){
f = AMP*test_func((double)i/O_RATE);
//f = rint(AMP*test_func((double)i/O_RATE));
fprintf(out,"%d %d %d %g %g\n",i,
o_buf[i],0,
f,o_buf[i]-f);
}
sum10k=0;
sum22k=0;
n10k=0;
n22k=0;
for(i=0;i<O_RATE;i++){
f = AMP*test_func((double)i/O_RATE);
//f = rint(AMP*test_func((double)i/O_RATE));
x = o_buf[i]-f;
if(((0.5*i)/O_RATE*I_RATE)<10000){
sum10k += x*x;
n10k++;
}
if(((0.5*i)/O_RATE*I_RATE)<22050){
sum22k += x*x;
n22k++;
}
}
printf("average error 10k=%g 22k=%g\n",
sqrt(sum10k/n10k),
sqrt(sum22k/n22k));
}

View file

@ -1,11 +0,0 @@
filterdir = $(libdir)/gst
filter_LTLIBRARIES = libgstriff.la
libgstriff_la_SOURCES = gstriffparse.c gstriffencode.c gstriffutil.c
libgstriffincludedir = $(includedir)/gst/libs/gstriff
libgstriffinclude_HEADERS = gstriff.h
libgstriff_la_LIBADD = $(GST_LIBS)
libgstriff_la_CFLAGS = $(GST_CFLAGS) -funroll-all-loops -finline-functions -ffast-math

View file

@ -1,226 +0,0 @@
/* Gnome-Streamer
* 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 <gstriff.h>
//#define debug(format,args...) g_print(format,##args)
#define debug(format,args...)
GstRiff *gst_riff_new(GstRiffCallback function, gpointer data) {
GstRiff *riff;
riff = (GstRiff *)g_malloc(sizeof(GstRiff));
g_return_val_if_fail(riff != NULL, NULL);
riff->form = 0;
riff->chunks = NULL;
riff->state = 0;
riff->curoffset = 0;
riff->nextlikely = 0;
riff->new_tag_found = function;
riff->callback_data = data;
riff->incomplete_chunk = NULL;
riff->dataleft = NULL;
return riff;
}
gint gst_riff_next_buffer(GstRiff *riff,GstBuffer *buf,gulong off) {
gulong last, size;
GstRiffChunk *chunk;
g_return_val_if_fail (riff != NULL, GST_RIFF_EINVAL);
g_return_val_if_fail (buf != NULL, GST_RIFF_EINVAL);
g_return_val_if_fail (GST_BUFFER_DATA(buf) != NULL, GST_RIFF_EINVAL);
size = GST_BUFFER_SIZE(buf);
last = off + size;
debug("offset new buffer 0x%08lx size 0x%08x\n", off, GST_BUFFER_SIZE(buf));
if (riff->dataleft) {
gulong newsize;
debug("recovering left data\n");
newsize = riff->dataleft_size + size;
riff->dataleft = g_realloc(riff->dataleft, newsize);
memcpy (riff->dataleft+riff->dataleft_size, GST_BUFFER_DATA(buf), size);
gst_buffer_unref (buf);
buf = gst_buffer_new ();
GST_BUFFER_DATA(buf) = riff->dataleft;
GST_BUFFER_SIZE(buf) = newsize;
off -= riff->dataleft_size;
//last -= riff->dataleft_size;
riff->dataleft = NULL;
}
if (off == 0) {
guint32 *words = (guin32 *)GST_BUFFER_DATA(buf);
// don't even try to parse the head if it's not there FIXME
if (last < 12) {
riff->state = GST_RIFF_ENOTRIFF;
return riff->state;
}
//g_print("testing is 0x%08lx '%s'\n",words[0],gst_riff_id_to_fourcc(words[0]));
/* verify this is a valid RIFF file, first of all */
if (GUINT32_FROM_LE (words[0]) != GST_RIFF_TAG_RIFF) {
riff->state = GST_RIFF_ENOTRIFF;
return riff->state;
}
riff->form = GUINT32_FROM_LE (words[2]);
//g_print("form is 0x%08lx '%s'\n",words[2],gst_riff_id_to_fourcc(words[2]));
riff->nextlikely = 12; /* skip 'RIFF', length, and form */
// all OK here
riff->incomplete_chunk = NULL;
}
// if we have an incomplete chunk from the previous buffer
if (riff->incomplete_chunk) {
guint leftover;
debug("have incomplete chunk %08x filled\n", riff->incomplete_chunk_size);
leftover = riff->incomplete_chunk->size - riff->incomplete_chunk_size;
if (leftover <= size) {
debug("we can fill it from %08x with %08x bytes = %08x\n", riff->incomplete_chunk_size, leftover, riff->incomplete_chunk_size+leftover);
memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), leftover);
if (riff->new_tag_found) {
riff->new_tag_found(riff->incomplete_chunk, riff->callback_data);
}
g_free(riff->incomplete_chunk->data);
g_free(riff->incomplete_chunk);
riff->incomplete_chunk = NULL;
}
else {
debug("we cannot fill it %08x >= %08lx\n", leftover, size);
memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), size);
riff->incomplete_chunk_size += size;
return 0;
}
}
if ((riff->nextlikely+12) > last) {
guint left = last - riff->nextlikely;
debug("not enough data next 0x%08x last 0x%08lx %08x %08x\n",riff->nextlikely, last, left, off);
riff->dataleft = g_malloc(left);
riff->dataleft_size = left;
memcpy(riff->dataleft, GST_BUFFER_DATA(buf)+size-left, left);
return 0;
}
debug("next 0x%08x last 0x%08lx offset %08x\n",riff->nextlikely, last, off);
/* loop while the next likely chunk header is in this buffer */
while ((riff->nextlikely+12) <= last) {
guin32 *words = (guin32 *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely - off );
// loop over all of the chunks to check which one is finished
while (riff->chunks) {
chunk = g_list_nth_data(riff->chunks, 0);
debug("next 0x%08x offset 0x%08lx size 0x%08x\n",riff->nextlikely, chunk->offset, chunk->size);
if (riff->nextlikely >= chunk->offset+chunk->size) {
//g_print("found END LIST\n");
// we have the end of the chunk on the stack, remove it
riff->chunks = g_list_remove(riff->chunks, chunk);
}
else break;
}
debug("next likely chunk is at offset 0x%08x\n",riff->nextlikely);
chunk = (GstRiffChunk *)g_malloc (sizeof (GstRiffChunk));
g_return_val_if_fail (chunk != NULL, GST_RIFF_ENOMEM);
chunk->offset = riff->nextlikely+8; /* point to the actual data */
chunk->id = GUINT32_FROM_LE (words[0]));
chunk->size = GUINT32_FROM_LE (words[1]);
chunk->data = (gchar *)(words+2);
// we need word alignment
//if (chunk->size & 0x01) chunk->size++;
chunk->form = GUINT32_FROM_LE (words[2]); /* fill in the form, might not be valid */
if (chunk->id == GST_RIFF_TAG_LIST) {
//g_print("found LIST %s\n", gst_riff_id_to_fourcc(chunk->form));
riff->nextlikely += 12;
// we push the list chunk on our 'stack'
riff->chunks = g_list_prepend(riff->chunks,chunk);
// send the buffer to the listener if we have received a function
if (riff->new_tag_found) {
riff->new_tag_found(chunk, riff->callback_data);
}
}
else {
debug("chunk id offset %08x is 0x%08lx '%s' and is 0x%08lx long\n",riff->nextlikely, words[0],
gst_riff_id_to_fourcc(GUINT32_FROM_LE (words[0])), GUINT32_FROM_LE (words[1]));
riff->nextlikely += 8 + chunk->size; /* doesn't include hdr */
// if this buffer is incomplete
if (riff->nextlikely > last) {
guint left = size - (riff->nextlikely - chunk->size - off);
//g_print("make incomplete buffer %08x\n", left);
chunk->data = g_malloc(chunk->size);
memcpy(chunk->data, (gchar *)(words+2), left);
riff->incomplete_chunk = chunk;
riff->incomplete_chunk_size = left;
}
else {
// send the buffer to the listener if we have received a function
if (riff->new_tag_found) {
riff->new_tag_found(chunk, riff->callback_data);
}
g_free(chunk);
}
//riff->chunks = g_list_prepend(riff->chunks,chunk);
}
}
return 0;
}
gulong gst_riff_fourcc_to_id(gchar *fourcc) {
g_return_val_if_fail(fourcc != NULL, 0);
return (fourcc[0] << 0) | (fourcc[1] << 8) |
(fourcc[2] << 16) | (fourcc[3] << 24);
}
gchar *gst_riff_id_to_fourcc(gulong id) {
gchar *fourcc = (gchar *)g_malloc(5);
g_return_val_if_fail(fourcc != NULL, NULL);
fourcc[0] = (id >> 0) & 0xff;
fourcc[1] = (id >> 8) & 0xff;
fourcc[2] = (id >> 16) & 0xff;
fourcc[3] = (id >> 24) & 0xff;
fourcc[4] = 0;
return fourcc;
}

View file

@ -1,406 +0,0 @@
/* Gnome-Streamer
* 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 __GST_RIFF_H__
#define __GST_RIFF_H__
#include <gst/gst.h>
typedef enum {
GST_RIFF_OK = 0,
GST_RIFF_ENOTRIFF = -1,
GST_RIFF_EINVAL = -2,
GST_RIFF_ENOMEM = -3
} GstRiffReturn;
/* states */
typedef enum {
GST_RIFF_STATE_INITIAL = 0,
GST_RIFF_STATE_HASAVIH = 1,
GST_RIFF_STATE_HASSTRH = 2,
GST_RIFF_STATE_HASSTRF = 3,
GST_RIFF_STATE_MOVI = 4
} GstRiffParserState;
#define MAKE_FOUR_CC(a,b,c,d) ( ((guint32)a) | (((guint32)b)<< 8) | \
((guint32)c)<<16 | (((guint32)d)<<24) )
/* RIFF types */
#define GST_RIFF_RIFF_WAVE MAKE_FOUR_CC('W','A','V','E')
#define GST_RIFF_RIFF_AVI MAKE_FOUR_CC('A','V','I',' ')
/* tags */
#define GST_RIFF_TAG_RIFF MAKE_FOUR_CC('R','I','F','F')
#define GST_RIFF_TAG_RIFX MAKE_FOUR_CC('R','I','F','X')
#define GST_RIFF_TAG_LIST MAKE_FOUR_CC('L','I','S','T')
#define GST_RIFF_TAG_avih MAKE_FOUR_CC('a','v','i','h')
#define GST_RIFF_TAG_strd MAKE_FOUR_CC('s','t','r','d')
#define GST_RIFF_TAG_strh MAKE_FOUR_CC('s','t','r','h')
#define GST_RIFF_TAG_strf MAKE_FOUR_CC('s','t','r','f')
#define GST_RIFF_TAG_vedt MAKE_FOUR_CC('v','e','d','t')
#define GST_RIFF_TAG_JUNK MAKE_FOUR_CC('J','U','N','K')
#define GST_RIFF_TAG_idx1 MAKE_FOUR_CC('i','d','x','1')
/* WAV stuff */
#define GST_RIFF_TAG_fmt MAKE_FOUR_CC('f','m','t',' ')
#define GST_RIFF_TAG_data MAKE_FOUR_CC('d','a','t','a')
/* LIST types */
#define GST_RIFF_LIST_movi MAKE_FOUR_CC('m','o','v','i')
#define GST_RIFF_LIST_hdrl MAKE_FOUR_CC('h','d','r','l')
#define GST_RIFF_LIST_strl MAKE_FOUR_CC('s','t','r','l')
/* fcc types */
#define GST_RIFF_FCC_vids MAKE_FOUR_CC('v','i','d','s')
#define GST_RIFF_FCC_auds MAKE_FOUR_CC('a','u','d','s')
#define GST_RIFF_FCC_pads MAKE_FOUR_CC('p','a','d','s')
#define GST_RIFF_FCC_txts MAKE_FOUR_CC('t','x','t','s')
#define GST_RIFF_FCC_vidc MAKE_FOUR_CC('v','i','d','c')
#define GST_RIFF_FCC_iavs MAKE_FOUR_CC('i','a','v','s')
/* fcc handlers */
#define GST_RIFF_FCCH_RLE MAKE_FOUR_CC('R','L','E',' ')
#define GST_RIFF_FCCH_msvc MAKE_FOUR_CC('m','s','v','c')
#define GST_RIFF_FCCH_MSVC MAKE_FOUR_CC('M','S','V','C')
/*********Chunk Names***************/
#define GST_RIFF_FF00 MAKE_FOUR_CC(0xFF,0xFF,0x00,0x00)
#define GST_RIFF_00 MAKE_FOUR_CC( '0', '0',0x00,0x00)
#define GST_RIFF_01 MAKE_FOUR_CC( '0', '1',0x00,0x00)
#define GST_RIFF_02 MAKE_FOUR_CC( '0', '2',0x00,0x00)
#define GST_RIFF_03 MAKE_FOUR_CC( '0', '3',0x00,0x00)
#define GST_RIFF_04 MAKE_FOUR_CC( '0', '4',0x00,0x00)
#define GST_RIFF_05 MAKE_FOUR_CC( '0', '5',0x00,0x00)
#define GST_RIFF_06 MAKE_FOUR_CC( '0', '6',0x00,0x00)
#define GST_RIFF_07 MAKE_FOUR_CC( '0', '7',0x00,0x00)
#define GST_RIFF_00pc MAKE_FOUR_CC( '0', '0', 'p', 'c')
#define GST_RIFF_01pc MAKE_FOUR_CC( '0', '1', 'p', 'c')
#define GST_RIFF_00dc MAKE_FOUR_CC( '0', '0', 'd', 'c')
#define GST_RIFF_00dx MAKE_FOUR_CC( '0', '0', 'd', 'x')
#define GST_RIFF_00db MAKE_FOUR_CC( '0', '0', 'd', 'b')
#define GST_RIFF_00xx MAKE_FOUR_CC( '0', '0', 'x', 'x')
#define GST_RIFF_00id MAKE_FOUR_CC( '0', '0', 'i', 'd')
#define GST_RIFF_00rt MAKE_FOUR_CC( '0', '0', 'r', 't')
#define GST_RIFF_0021 MAKE_FOUR_CC( '0', '0', '2', '1')
#define GST_RIFF_00iv MAKE_FOUR_CC( '0', '0', 'i', 'v')
#define GST_RIFF_0031 MAKE_FOUR_CC( '0', '0', '3', '1')
#define GST_RIFF_0032 MAKE_FOUR_CC( '0', '0', '3', '2')
#define GST_RIFF_00vc MAKE_FOUR_CC( '0', '0', 'v', 'c')
#define GST_RIFF_00xm MAKE_FOUR_CC( '0', '0', 'x', 'm')
#define GST_RIFF_01wb MAKE_FOUR_CC( '0', '1', 'w', 'b')
#define GST_RIFF_01dc MAKE_FOUR_CC( '0', '1', 'd', 'c')
#define GST_RIFF_00__ MAKE_FOUR_CC( '0', '0', '_', '_')
/*********VIDEO CODECS**************/
#define GST_RIFF_cram MAKE_FOUR_CC( 'c', 'r', 'a', 'm')
#define GST_RIFF_CRAM MAKE_FOUR_CC( 'C', 'R', 'A', 'M')
#define GST_RIFF_wham MAKE_FOUR_CC( 'w', 'h', 'a', 'm')
#define GST_RIFF_WHAM MAKE_FOUR_CC( 'W', 'H', 'A', 'M')
#define GST_RIFF_rgb MAKE_FOUR_CC(0x00,0x00,0x00,0x00)
#define GST_RIFF_RGB MAKE_FOUR_CC( 'R', 'G', 'B', ' ')
#define GST_RIFF_rle8 MAKE_FOUR_CC(0x01,0x00,0x00,0x00)
#define GST_RIFF_RLE8 MAKE_FOUR_CC( 'R', 'L', 'E', '8')
#define GST_RIFF_rle4 MAKE_FOUR_CC(0x02,0x00,0x00,0x00)
#define GST_RIFF_RLE4 MAKE_FOUR_CC( 'R', 'L', 'E', '4')
#define GST_RIFF_none MAKE_FOUR_CC(0x00,0x00,0xFF,0xFF)
#define GST_RIFF_NONE MAKE_FOUR_CC( 'N', 'O', 'N', 'E')
#define GST_RIFF_pack MAKE_FOUR_CC(0x01,0x00,0xFF,0xFF)
#define GST_RIFF_PACK MAKE_FOUR_CC( 'P', 'A', 'C', 'K')
#define GST_RIFF_tran MAKE_FOUR_CC(0x02,0x00,0xFF,0xFF)
#define GST_RIFF_TRAN MAKE_FOUR_CC( 'T', 'R', 'A', 'N')
#define GST_RIFF_ccc MAKE_FOUR_CC(0x03,0x00,0xFF,0xFF)
#define GST_RIFF_CCC MAKE_FOUR_CC( 'C', 'C', 'C', ' ')
#define GST_RIFF_cyuv MAKE_FOUR_CC( 'c', 'y', 'u', 'v')
#define GST_RIFF_CYUV MAKE_FOUR_CC( 'C', 'Y', 'U', 'V')
#define GST_RIFF_jpeg MAKE_FOUR_CC(0x04,0x00,0xFF,0xFF)
#define GST_RIFF_JPEG MAKE_FOUR_CC( 'J', 'P', 'E', 'G')
#define GST_RIFF_MJPG MAKE_FOUR_CC( 'M', 'J', 'P', 'G')
#define GST_RIFF_mJPG MAKE_FOUR_CC( 'm', 'J', 'P', 'G')
#define GST_RIFF_IJPG MAKE_FOUR_CC( 'I', 'J', 'P', 'G')
#define GST_RIFF_rt21 MAKE_FOUR_CC( 'r', 't', '2', '1')
#define GST_RIFF_RT21 MAKE_FOUR_CC( 'R', 'T', '2', '1')
#define GST_RIFF_iv31 MAKE_FOUR_CC( 'i', 'v', '3', '1')
#define GST_RIFF_IV31 MAKE_FOUR_CC( 'I', 'V', '3', '1')
#define GST_RIFF_iv32 MAKE_FOUR_CC( 'i', 'v', '3', '2')
#define GST_RIFF_IV32 MAKE_FOUR_CC( 'I', 'V', '3', '2')
#define GST_RIFF_iv41 MAKE_FOUR_CC( 'i', 'v', '4', '1')
#define GST_RIFF_IV41 MAKE_FOUR_CC( 'I', 'V', '4', '1')
#define GST_RIFF_iv50 MAKE_FOUR_CC( 'i', 'v', '5', '0')
#define GST_RIFF_IV50 MAKE_FOUR_CC( 'I', 'V', '5', '0')
#define GST_RIFF_cvid MAKE_FOUR_CC( 'c', 'v', 'i', 'd')
#define GST_RIFF_CVID MAKE_FOUR_CC( 'C', 'V', 'I', 'D')
#define GST_RIFF_ULTI MAKE_FOUR_CC( 'U', 'L', 'T', 'I')
#define GST_RIFF_ulti MAKE_FOUR_CC( 'u', 'l', 't', 'i')
#define GST_RIFF_YUV9 MAKE_FOUR_CC( 'Y', 'V', 'U', '9')
#define GST_RIFF_YVU9 MAKE_FOUR_CC( 'Y', 'U', 'V', '9')
#define GST_RIFF_XMPG MAKE_FOUR_CC( 'X', 'M', 'P', 'G')
#define GST_RIFF_xmpg MAKE_FOUR_CC( 'x', 'm', 'p', 'g')
#define GST_RIFF_VDOW MAKE_FOUR_CC( 'V', 'D', 'O', 'W')
#define GST_RIFF_MVI1 MAKE_FOUR_CC( 'M', 'V', 'I', '1')
#define GST_RIFF_v422 MAKE_FOUR_CC( 'v', '4', '2', '2')
#define GST_RIFF_V422 MAKE_FOUR_CC( 'V', '4', '2', '2')
#define GST_RIFF_mvi1 MAKE_FOUR_CC( 'm', 'v', 'i', '1')
#define GST_RIFF_MPIX MAKE_FOUR_CC(0x04,0x00, 'i', '1') /* MotionPixels munged their id */
#define GST_RIFF_AURA MAKE_FOUR_CC( 'A', 'U', 'R', 'A')
#define GST_RIFF_DMB1 MAKE_FOUR_CC( 'D', 'M', 'B', '1')
#define GST_RIFF_dmb1 MAKE_FOUR_CC( 'd', 'm', 'b', '1')
#define GST_RIFF_BW10 MAKE_FOUR_CC( 'B', 'W', '1', '0')
#define GST_RIFF_bw10 MAKE_FOUR_CC( 'b', 'w', '1', '0')
#define GST_RIFF_yuy2 MAKE_FOUR_CC( 'y', 'u', 'y', '2')
#define GST_RIFF_YUY2 MAKE_FOUR_CC( 'Y', 'U', 'Y', '2')
#define GST_RIFF_YUV8 MAKE_FOUR_CC( 'Y', 'U', 'V', '8')
#define GST_RIFF_WINX MAKE_FOUR_CC( 'W', 'I', 'N', 'X')
#define GST_RIFF_WPY2 MAKE_FOUR_CC( 'W', 'P', 'Y', '2')
#define GST_RIFF_m263 MAKE_FOUR_CC( 'm', '2', '6', '3')
#define GST_RIFF_M263 MAKE_FOUR_CC( 'M', '2', '6', '3')
#define GST_RIFF_Q1_0 MAKE_FOUR_CC( 'Q', '1',0x2e, '0')
#define GST_RIFF_SFMC MAKE_FOUR_CC( 'S', 'F', 'M', 'C')
#define GST_RIFF_y41p MAKE_FOUR_CC( 'y', '4', '1', 'p')
#define GST_RIFF_Y41P MAKE_FOUR_CC( 'Y', '4', '1', 'P')
#define GST_RIFF_yv12 MAKE_FOUR_CC( 'y', 'v', '1', '2')
#define GST_RIFF_YV12 MAKE_FOUR_CC( 'Y', 'V', '1', '2')
#define GST_RIFF_vixl MAKE_FOUR_CC( 'v', 'i', 'x', 'l')
#define GST_RIFF_VIXL MAKE_FOUR_CC( 'V', 'I', 'X', 'L')
#define GST_RIFF_iyuv MAKE_FOUR_CC( 'i', 'y', 'u', 'v')
#define GST_RIFF_IYUV MAKE_FOUR_CC( 'I', 'Y', 'U', 'V')
#define GST_RIFF_i420 MAKE_FOUR_CC( 'i', '4', '2', '0')
#define GST_RIFF_I420 MAKE_FOUR_CC( 'I', '4', '2', '0')
#define GST_RIFF_vyuy MAKE_FOUR_CC( 'v', 'y', 'u', 'y')
#define GST_RIFF_VYUY MAKE_FOUR_CC( 'V', 'Y', 'U', 'Y')
#define GST_RIFF_DIV3 MAKE_FOUR_CC( 'D', 'I', 'V', '3')
#define GST_RIFF_rpza MAKE_FOUR_CC( 'r', 'p', 'z', 'a')
/* And this here's the mistakes that need to be supported */
#define GST_RIFF_azpr MAKE_FOUR_CC( 'a', 'z', 'p', 'r') /* recognize Apple's rpza mangled? */
/*********** FND in MJPG **********/
#define GST_RIFF_ISFT MAKE_FOUR_CC( 'I', 'S', 'F', 'T')
#define GST_RIFF_IDIT MAKE_FOUR_CC( 'I', 'D', 'I', 'T')
#define GST_RIFF_00AM MAKE_FOUR_CC( '0', '0', 'A', 'M')
#define GST_RIFF_DISP MAKE_FOUR_CC( 'D', 'I', 'S', 'P')
#define GST_RIFF_ISBJ MAKE_FOUR_CC( 'I', 'S', 'B', 'J')
#define GST_RIFF_rec MAKE_FOUR_CC( 'r', 'e', 'c', ' ')
/* common data structures */
struct _gst_riff_avih {
guint32 us_frame; /* microsec per frame */
guint32 max_bps; /* byte/s overall */
guint32 pad_gran; /* pad_gran (???) */
guint32 flags;
/* flags values */
#define GST_RIFF_AVIH_HASINDEX 0x00000010 /* has idx1 chunk */
#define GST_RIFF_AVIH_MUSTUSEINDEX 0x00000020 /* must use idx1 chunk to determine order */
#define GST_RIFF_AVIH_ISINTERLEAVED 0x00000100 /* AVI file is interleaved */
#define GST_RIFF_AVIH_WASCAPTUREFILE 0x00010000 /* specially allocated used for capturing real time video */
#define GST_RIFF_AVIH_COPYRIGHTED 0x00020000 /* contains copyrighted data */
guint32 tot_frames; /* # of frames (all) */
guint32 init_frames; /* initial frames (???) */
guint32 streams;
guint32 bufsize; /* suggested buffer size */
guint32 width;
guint32 height;
guint32 scale;
guint32 rate;
guint32 start;
guint32 length;
};
struct _gst_riff_strh {
guint32 type; /* stream type */
guint32 fcc_handler; /* fcc_handler */
guint32 flags;
/* flags values */
#define GST_RIFF_STRH_DISABLED 0x000000001
#define GST_RIFF_STRH_VIDEOPALCHANGES 0x000010000
guint32 priority;
guint32 init_frames; /* initial frames (???) */
guint32 scale;
guint32 rate;
guint32 start;
guint32 length;
guint32 bufsize; /* suggested buffer size */
guint32 quality;
guint32 samplesize;
/* XXX 16 bytes ? */
};
struct _gst_riff_strf_vids { /* == BitMapInfoHeader */
guint32 size;
guint32 width;
guint32 height;
guint16 planes;
guint16 bit_cnt;
guint32 compression;
guint32 image_size;
guint32 xpels_meter;
guint32 ypels_meter;
guint32 num_colors; /* used colors */
guint32 imp_colors; /* important colors */
/* may be more for some codecs */
};
struct _gst_riff_strf_auds { /* == WaveHeader (?) */
guint16 format;
/**** from public Microsoft RIFF docs ******/
#define GST_RIFF_WAVE_FORMAT_UNKNOWN (0x0000)
#define GST_RIFF_WAVE_FORMAT_PCM (0x0001)
#define GST_RIFF_WAVE_FORMAT_ADPCM (0x0002)
#define GST_RIFF_WAVE_FORMAT_IBM_CVSD (0x0005)
#define GST_RIFF_WAVE_FORMAT_ALAW (0x0006)
#define GST_RIFF_WAVE_FORMAT_MULAW (0x0007)
#define GST_RIFF_WAVE_FORMAT_OKI_ADPCM (0x0010)
#define GST_RIFF_WAVE_FORMAT_DVI_ADPCM (0x0011)
#define GST_RIFF_WAVE_FORMAT_DIGISTD (0x0015)
#define GST_RIFF_WAVE_FORMAT_DIGIFIX (0x0016)
#define GST_RIFF_WAVE_FORMAT_YAMAHA_ADPCM (0x0020)
#define GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH (0x0022)
#define GST_RIFF_WAVE_FORMAT_GSM610 (0x0031)
#define GST_RIFF_WAVE_FORMAT_MSN (0x0032)
#define GST_RIFF_WAVE_FORMAT_MPEGL12 (0x0050)
#define GST_RIFF_WAVE_FORMAT_MPEGL3 (0x0055)
#define GST_RIFF_IBM_FORMAT_MULAW (0x0101)
#define GST_RIFF_IBM_FORMAT_ALAW (0x0102)
#define GST_RIFF_IBM_FORMAT_ADPCM (0x0103)
#define GST_RIFF_WAVE_FORMAT_DIVX (0x0160)
#define GST_RIFF_WAVE_FORMAT_divx (0x0161)
guint16 channels;
guint32 rate;
guint32 av_bps;
guint16 blockalign;
guint16 size;
};
struct _gst_riff_strf_iavs {
guint32 DVAAuxSrc;
guint32 DVAAuxCtl;
guint32 DVAAuxSrc1;
guint32 DVAAuxCtl1;
guint32 DVVAuxSrc;
guint32 DVVAuxCtl;
guint32 DVReserved1;
guint32 DVReserved2;
};
struct _gst_riff_riff {
guint32 id;
guint32 size;
guint32 type;
};
struct _gst_riff_list {
guint32 id;
guint32 size;
guint32 type;
};
struct _gst_riff_chunk {
guint32 id;
guint32 size;
};
struct _gst_riff_index_entry {
guint32 id;
guint32 flags;
#define GST_RIFF_IF_LIST (0x00000001L)
#define GST_RIFF_IF_KEYFRAME (0x00000010L)
#define GST_RIFF_IF_NO_TIME (0x00000100L)
#define GST_RIFF_IF_COMPUSE (0x0FFF0000L)
guint32 offset;
guint32 size;
};
typedef struct _gst_riff_riff gst_riff_riff;
typedef struct _gst_riff_list gst_riff_list;
typedef struct _gst_riff_chunk gst_riff_chunk;
typedef struct _gst_riff_index_entry gst_riff_index_entry;
typedef struct _gst_riff_avih gst_riff_avih;
typedef struct _gst_riff_strh gst_riff_strh;
typedef struct _gst_riff_strf_vids gst_riff_strf_vids;
typedef struct _gst_riff_strf_auds gst_riff_strf_auds;
typedef struct _gst_riff_strf_iavs gst_riff_strf_iavs;
typedef struct _GstRiff GstRiff;
typedef struct _GstRiffChunk GstRiffChunk;
typedef void (*GstRiffCallback) (GstRiffChunk *chunk, gpointer data);
struct _GstRiff {
guint32 form;
/* list of chunks, most recent at the head */
GList *chunks;
/* incomplete chunks are assembled here */
GstRiffChunk *incomplete_chunk;
guint32 incomplete_chunk_size;
/* parse state */
GstRiffParserState state;
guint32 curoffset;
guint32 nextlikely;
/* leftover data */
guchar *dataleft;
guint32 dataleft_size;
/* callback function and data pointer */
GstRiffCallback new_tag_found;
gpointer callback_data;
};
struct _GstRiffChunk {
gulong offset;
guint32 id;
guint32 size;
guint32 form; /* for list chunks */
gchar *data;
};
/* from gstriffparse.c */
GstRiff* gst_riff_parser_new (GstRiffCallback function, gpointer data);
GstRiffReturn gst_riff_parser_next_buffer (GstRiff *riff, GstBuffer *buf, gulong off);
void gst_riff_parser_resync (GstRiff *riff, gulong offset);
/* from gstriffencode.c */
GstRiff* gst_riff_encoder_new (guint32 type);
GstRiffReturn gst_riff_encoder_avih (GstRiff *riff, gst_riff_avih *head, gulong size);
GstRiffReturn gst_riff_encoder_strh (GstRiff *riff, guint32 fcc_type,
gst_riff_strh *head, gulong size);
GstRiffReturn gst_riff_encoder_strf (GstRiff *riff, void *format, gulong size);
GstRiffReturn gst_riff_encoder_chunk (GstRiff *riff, guint32 chunk_type,
void *chunk, gulong size);
GstBuffer* gst_riff_encoder_get_buffer (GstRiff *riff);
GstBuffer* gst_riff_encoder_get_and_reset_buffer (GstRiff *riff);
/* from gstriffutil.c */
gulong gst_riff_fourcc_to_id (gchar *fourcc);
gchar* gst_riff_id_to_fourcc (gulong id);
#endif /* __GST_RIFF_H__ */

View file

@ -1,177 +0,0 @@
/* Gnome-Streamer
* 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 <string.h>
//#define DEBUG_ENABLED
#include "gstriff.h"
#define GST_RIFF_ENCODER_BUF_SIZE 1024
#define ADD_CHUNK(riffenc, chunkid, chunksize) \
{ \
gst_riff_chunk *chunk;\
chunk = (gst_riff_chunk *)(riffenc->dataleft + riffenc->nextlikely);\
chunk->id = chunkid; \
chunk->size = chunksize; \
riffenc->nextlikely += sizeof(gst_riff_chunk); \
}
#define ADD_LIST(riffenc, listsize, listtype) \
{ \
gst_riff_list *list;\
list = (gst_riff_list *)(riffenc->dataleft + riffenc->nextlikely); \
list->id = GST_RIFF_TAG_LIST; \
list->size = listsize; \
list->type = listtype; \
riffenc->nextlikely += sizeof(gst_riff_list); \
}
GstRiff *gst_riff_encoder_new(guint32 type) {
GstRiff *riff;
gst_riff_list *list;
GST_DEBUG (0,"gst_riff_encoder: making %4.4s encoder\n", (char *)&type);
riff = (GstRiff *)g_malloc(sizeof(GstRiff));
g_return_val_if_fail(riff != NULL, NULL);
riff->form = 0;
riff->chunks = NULL;
riff->state = GST_RIFF_STATE_INITIAL;
riff->curoffset = 0;
riff->incomplete_chunk = NULL;
riff->dataleft = g_malloc(GST_RIFF_ENCODER_BUF_SIZE);
riff->dataleft_size = GST_RIFF_ENCODER_BUF_SIZE;
riff->nextlikely = 0;
list = (gst_riff_list *)riff->dataleft;
list->id = GST_RIFF_TAG_RIFF;
list->size = 0x00FFFFFF;
list->type = GST_RIFF_RIFF_AVI;
riff->nextlikely += sizeof(gst_riff_list);
return riff;
}
gint gst_riff_encoder_avih(GstRiff *riff, gst_riff_avih *head, gulong size) {
gst_riff_chunk *chunk;
g_return_val_if_fail(riff->state == GST_RIFF_STATE_INITIAL, GST_RIFF_EINVAL);
GST_DEBUG (0,"gst_riff_encoder: add avih\n");
ADD_LIST(riff, 0xB8, GST_RIFF_LIST_hdrl);
ADD_CHUNK(riff, GST_RIFF_TAG_avih, size);
chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely);
memcpy(chunk, head, size);
riff->nextlikely += size;
riff->state = GST_RIFF_STATE_HASAVIH;
return GST_RIFF_OK;
}
gint gst_riff_encoder_strh(GstRiff *riff, guint32 fcc_type, gst_riff_strh *head, gulong size) {
gst_riff_chunk *chunk;
g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASAVIH ||
riff->state == GST_RIFF_STATE_HASSTRF, GST_RIFF_EINVAL);
GST_DEBUG (0,"gst_riff_encoder: add strh type %08x (%4.4s)\n", fcc_type, (char *)&fcc_type);
ADD_LIST(riff, 108, GST_RIFF_LIST_strl);
ADD_CHUNK(riff, GST_RIFF_TAG_strh, size);
chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely);
head->type = fcc_type;
memcpy(chunk, head, size);
riff->nextlikely += size;
riff->state = GST_RIFF_STATE_HASSTRH;
return GST_RIFF_OK;
}
gint gst_riff_encoder_strf(GstRiff *riff, void *format, gulong size) {
gst_riff_chunk *chunk;
g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASSTRH, GST_RIFF_EINVAL);
GST_DEBUG (0,"gst_riff_encoder: add strf\n");
ADD_CHUNK(riff, GST_RIFF_TAG_strf, size);
chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely);
memcpy(chunk, format, size);
riff->nextlikely += size;
riff->state = GST_RIFF_STATE_HASSTRF;
return GST_RIFF_OK;
}
gint gst_riff_encoder_chunk(GstRiff *riff, guint32 chunk_type, void *chunkdata, gulong size) {
gst_riff_chunk *chunk;
g_return_val_if_fail(riff->state == GST_RIFF_STATE_HASSTRF ||
riff->state == GST_RIFF_STATE_MOVI, GST_RIFF_EINVAL);
if (riff->state != GST_RIFF_STATE_MOVI) {
ADD_LIST(riff, 0x00FFFFFF, GST_RIFF_LIST_movi);
riff->state = GST_RIFF_STATE_MOVI;
}
GST_DEBUG (0,"gst_riff_encoder: add chunk type %08x (%4.4s)\n", chunk_type, (char *)&chunk_type);
ADD_CHUNK(riff, chunk_type, size);
if (chunkdata != NULL) {
chunk = (gst_riff_chunk *)(riff->dataleft + riff->nextlikely);
memcpy(chunk, chunkdata, size);
riff->nextlikely += size + (size&1);
}
return GST_RIFF_OK;
}
GstBuffer *gst_riff_encoder_get_buffer(GstRiff *riff) {
GstBuffer *newbuf;
newbuf = gst_buffer_new();
GST_BUFFER_DATA(newbuf) = riff->dataleft;
GST_BUFFER_SIZE(newbuf) = riff->nextlikely;
return newbuf;
}
GstBuffer *gst_riff_encoder_get_and_reset_buffer(GstRiff *riff) {
GstBuffer *newbuf;
newbuf = gst_riff_encoder_get_buffer(riff);
riff->dataleft = g_malloc(GST_RIFF_ENCODER_BUF_SIZE);
riff->dataleft_size = GST_RIFF_ENCODER_BUF_SIZE;
riff->nextlikely = 0;
return newbuf;
}

View file

@ -1,221 +0,0 @@
/* Gnome-Streamer
* 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 <string.h>
//#define DEBUG_ENABLED
#include <gstriff.h>
GstRiff*
gst_riff_parser_new (GstRiffCallback function, gpointer data)
{
GstRiff *riff;
riff = (GstRiff *)g_malloc(sizeof(GstRiff));
g_return_val_if_fail(riff != NULL, NULL);
riff->form = 0;
riff->chunks = NULL;
riff->state = 0;
riff->curoffset = 0;
riff->nextlikely = 0;
riff->new_tag_found = function;
riff->callback_data = data;
riff->incomplete_chunk = NULL;
riff->dataleft = NULL;
return riff;
}
gint
gst_riff_parser_next_buffer (GstRiff *riff, GstBuffer *buf, gulong off)
{
gulong last, size;
GstRiffChunk *chunk;
g_return_val_if_fail(riff != NULL, GST_RIFF_EINVAL);
g_return_val_if_fail(buf != NULL, GST_RIFF_EINVAL);
g_return_val_if_fail(GST_BUFFER_DATA(buf) != NULL, GST_RIFF_EINVAL);
size = GST_BUFFER_SIZE(buf);
last = off + size;
GST_DEBUG (0,"gst_riff_parser: offset new buffer 0x%08lx size 0x%08x\n", off, GST_BUFFER_SIZE(buf));
if (riff->dataleft) {
gulong newsize;
GST_DEBUG (0,"gst_riff_parser: recovering left data\n");
newsize = riff->dataleft_size + size;
riff->dataleft = g_realloc(riff->dataleft, newsize);
memcpy(riff->dataleft+riff->dataleft_size, GST_BUFFER_DATA(buf), size);
gst_buffer_unref(buf);
buf = gst_buffer_new();
GST_BUFFER_DATA(buf) = riff->dataleft;
size = GST_BUFFER_SIZE(buf) = newsize;
off -= riff->dataleft_size;
//last -= riff->dataleft_size;
riff->dataleft = NULL;
}
if (off == 0) {
guint32 *words = (guint32 *)GST_BUFFER_DATA(buf);
// don't even try to parse the head if it's not there FIXME
if (last < 12) {
riff->state = GST_RIFF_ENOTRIFF;
return riff->state;
}
//g_print("testing is 0x%08lx '%s'\n",words[0],gst_riff_id_to_fourcc(words[0]));
/* verify this is a valid RIFF file, first of all */
if (GUINT32_FROM_LE (words[0]) != GST_RIFF_TAG_RIFF) {
riff->state = GST_RIFF_ENOTRIFF;
return riff->state;
}
riff->form = GUINT32_FROM_LE (words[2]);
//g_print("form is 0x%08lx '%s'\n",words[2],gst_riff_id_to_fourcc(words[2]));
riff->nextlikely = 12; /* skip 'RIFF', length, and form */
// all OK here
riff->incomplete_chunk = NULL;
}
// if we have an incomplete chunk from the previous buffer
if (riff->incomplete_chunk) {
guint leftover;
GST_DEBUG (0,"gst_riff_parser: have incomplete chunk %08x filled\n", riff->incomplete_chunk_size);
leftover = riff->incomplete_chunk->size - riff->incomplete_chunk_size;
if (leftover <= size) {
GST_DEBUG (0,"gst_riff_parser: we can fill it from %08x with %08x bytes = %08x\n",
riff->incomplete_chunk_size, leftover,
riff->incomplete_chunk_size+leftover);
memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), leftover);
if (riff->new_tag_found) {
riff->new_tag_found(riff->incomplete_chunk, riff->callback_data);
}
g_free(riff->incomplete_chunk->data);
g_free(riff->incomplete_chunk);
riff->incomplete_chunk = NULL;
}
else {
GST_DEBUG (0,"gst_riff_parser: we cannot fill it %08x >= %08lx\n", leftover, size);
memcpy(riff->incomplete_chunk->data+riff->incomplete_chunk_size, GST_BUFFER_DATA(buf), size);
riff->incomplete_chunk_size += size;
return 0;
}
}
if (riff->nextlikely & 0x01) riff->nextlikely++;
GST_DEBUG (0,"gst_riff_parser: next 0x%08x last 0x%08lx offset %08lx\n",riff->nextlikely, last, off);
/* loop while the next likely chunk header is in this buffer */
while ((riff->nextlikely+12) <= last) {
guint32 *words = (guint32 *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely - off );
// loop over all of the chunks to check which one is finished
while (riff->chunks) {
chunk = g_list_nth_data(riff->chunks, 0);
GST_DEBUG (0,"gst_riff_parser: next 0x%08x offset 0x%08lx size 0x%08x\n",riff->nextlikely,
chunk->offset, chunk->size);
if (riff->nextlikely >= chunk->offset+chunk->size) {
GST_DEBUG (0,"gst_riff_parser: found END LIST\n");
// we have the end of the chunk on the stack, remove it
riff->chunks = g_list_remove(riff->chunks, chunk);
}
else break;
}
GST_DEBUG (0,"gst_riff_parser: next likely chunk is at offset 0x%08x\n",riff->nextlikely);
chunk = (GstRiffChunk *)g_malloc(sizeof(GstRiffChunk));
g_return_val_if_fail(chunk != NULL, GST_RIFF_ENOMEM);
chunk->offset = riff->nextlikely+8; /* point to the actual data */
chunk->id = GUINT32_FROM_LE (words[0]);
chunk->size = GUINT32_FROM_LE (words[1]);
chunk->data = (gchar *)(words+2);
// we need word alignment
//if (chunk->size & 0x01) chunk->size++;
chunk->form = GUINT32_FROM_LE (words[2]); /* fill in the form, might not be valid */
if (chunk->id == GST_RIFF_TAG_LIST) {
GST_DEBUG (0,"found LIST %s\n", gst_riff_id_to_fourcc(chunk->form));
riff->nextlikely += 12;
// we push the list chunk on our 'stack'
riff->chunks = g_list_prepend(riff->chunks,chunk);
// send the buffer to the listener if we have received a function
if (riff->new_tag_found) {
riff->new_tag_found(chunk, riff->callback_data);
}
}
else {
GST_DEBUG (0,"gst_riff_parser: chunk id offset %08x is 0x%08x '%s' and is 0x%08x long\n",
riff->nextlikely, GUINT32_FROM_LE (words[0]),
gst_riff_id_to_fourcc(GUINT32_FROM_LE (words[0])), GUINT32_FROM_LE (words[1]));
riff->nextlikely += 8 + chunk->size; /* doesn't include hdr */
// if this buffer is incomplete
if (riff->nextlikely > last) {
guint left = size - (riff->nextlikely - chunk->size - off);
GST_DEBUG (0,"make incomplete buffer %08x\n", left);
chunk->data = g_malloc(chunk->size);
memcpy(chunk->data, (gchar *)(words+2), left);
riff->incomplete_chunk = chunk;
riff->incomplete_chunk_size = left;
}
else {
// send the buffer to the listener if we have received a function
if (riff->new_tag_found) {
riff->new_tag_found(chunk, riff->callback_data);
}
g_free(chunk);
}
if (riff->nextlikely & 0x01) riff->nextlikely++;
//riff->chunks = g_list_prepend(riff->chunks,chunk);
}
}
if ((riff->nextlikely+12) > last && !riff->incomplete_chunk) {
guint left = last - riff->nextlikely;
GST_DEBUG (0,"gst_riff_parser: not enough data next 0x%08x last 0x%08lx %08x %08lx\n",riff->nextlikely,
last, left, off);
riff->dataleft = g_malloc(left);
riff->dataleft_size = left;
memcpy(riff->dataleft, GST_BUFFER_DATA(buf)+size-left, left);
return 0;
}
return 0;
}
void
gst_riff_parser_resync (GstRiff *riff, gulong offset)
{
riff->incomplete_chunk = NULL;
riff->dataleft = NULL;
riff->nextlikely = offset;
}

View file

@ -1,46 +0,0 @@
/* Gnome-Streamer
* 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 <gstriff.h>
//#define debug(format,args...) g_print(format,##args)
#define debug(format,args...)
gulong gst_riff_fourcc_to_id(gchar *fourcc) {
g_return_val_if_fail(fourcc != NULL, 0);
return (fourcc[0] << 0) | (fourcc[1] << 8) |
(fourcc[2] << 16) | (fourcc[3] << 24);
}
gchar *gst_riff_id_to_fourcc(gulong id) {
gchar *fourcc = (gchar *)g_malloc(5);
g_return_val_if_fail(fourcc != NULL, NULL);
fourcc[0] = (id >> 0) & 0xff;
fourcc[1] = (id >> 8) & 0xff;
fourcc[2] = (id >> 16) & 0xff;
fourcc[3] = (id >> 24) & 0xff;
fourcc[4] = 0;
return fourcc;
}