mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
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:
parent
7ec6702121
commit
107feed0de
52 changed files with 0 additions and 9612 deletions
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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 ();
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
8
libs/getbits/.gitignore
vendored
8
libs/getbits/.gitignore
vendored
|
@ -1,8 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
||||
gbtest
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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__ */
|
8
libs/idct/.gitignore
vendored
8
libs/idct/.gitignore
vendored
|
@ -1,8 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
||||
ieeetest
|
|
@ -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
|
|
@ -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.
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
7
libs/putbits/.gitignore
vendored
7
libs/putbits/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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)
|
|
@ -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...
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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__ */
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue