vorbis: have a copy_sample func as a func pointer

Make some more variants for copy_sample funcs and use them via function pointer.
This commit is contained in:
Stefan Kost 2010-05-06 08:20:10 +03:00
parent 51739d562c
commit 4e6cb3e91f
4 changed files with 161 additions and 18 deletions

View file

@ -588,11 +588,18 @@ vorbis_handle_identification_packet (GstVorbisDec * vd)
s = gst_caps_get_structure (caps, 0);
/* template ensures 16 or 32 */
gst_structure_get_int (s, "width", &width);
GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth",
gst_structure_get_name (s), vd->vi.channels, width);
}
gst_caps_unref (caps);
}
vd->width = width >> 3;
/* select a copy_samples function, this way we can have specialized versions
* for mono/stereo and avoid the depth switch in tremor case */
vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width);
caps = gst_caps_copy (gst_pad_get_pad_template_caps (vd->srcpad));
gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate,
"channels", G_TYPE_INT, vd->vi.channels,
@ -881,8 +888,8 @@ vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet,
goto wrong_samples;
/* copy samples in buffer */
copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm, sample_count,
vd->vi.channels, vd->width);
vd->copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm,
sample_count, vd->vi.channels, vd->width);
GST_LOG_OBJECT (vd, "setting output size to %d", size);
GST_BUFFER_SIZE (out) = size;

View file

@ -75,6 +75,8 @@ struct _GstVorbisDec {
GList *pendingevents;
GstTagList *taglist;
CopySampleFunc copy_samples;
};
struct _GstVorbisDecClass {

View file

@ -26,25 +26,51 @@
#include "config.h"
#endif
#include <string.h>
#include "gstvorbisdeclib.h"
#ifndef TREMOR
/* These samples can be outside of the float -1.0 -- 1.0 range, this
* is allowed, downstream elements are supposed to clip */
void
static void
copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
gint channels, gint width)
{
memcpy (out, in[0], samples * sizeof (float));
}
static void
copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
gint channels, gint width)
{
#ifdef GST_VORBIS_DEC_SEQUENTIAL
memcpy (out, in[0], samples * sizeof (float));
out += samples;
memcpy (out, in[1], samples * sizeof (float));
#else
gint j;
for (j = 0; j < samples; j++) {
*out++ = in[0][j];
*out++ = in[1][j];
}
#endif
}
static void
copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
gint channels, gint width)
{
gint i, j;
g_assert (width == 4);
#ifdef GST_VORBIS_DEC_SEQUENTIAL
gint i;
for (i = 0; i < channels; i++) {
memcpy (out, in[i], samples * sizeof (float));
out += samples;
}
#else
gint i, j;
for (j = 0; j < samples; j++) {
for (i = 0; i < channels; i++) {
*out++ = in[i][j];
@ -53,6 +79,28 @@ copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
#endif
}
CopySampleFunc
get_copy_sample_func (gint channels, gint width)
{
CopySampleFunc f = NULL;
g_assert (width == 4);
switch (channels) {
case 1:
f = copy_samples_m;
break;
case 2:
f = copy_samples_s;
break;
default:
f = copy_samples;
break;
}
return f;
}
#else
/* Taken from Tremor, misc.h */
@ -83,8 +131,38 @@ CLIP_TO_15 (ogg_int32_t x)
#endif
static void
copy_samples_32 (gint32 * out, ogg_int32_t ** in, guint samples, gint channels)
copy_samples_32_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
guint samples, gint channels, gint width)
{
gint32 *out = (gint32 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint j;
for (j = 0; j < samples; j++) {
*out++ = CLIP_TO_15 (in[0][j] >> 9);
}
}
static void
copy_samples_32_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
guint samples, gint channels, gint width)
{
gint32 *out = (gint32 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint j;
for (j = 0; j < samples; j++) {
*out++ = CLIP_TO_15 (in[0][j] >> 9);
*out++ = CLIP_TO_15 (in[1][j] >> 9);
}
}
static void
copy_samples_32 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
gint channels, gint width)
{
gint32 *out = (gint32 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint i, j;
for (j = 0; j < samples; j++) {
@ -95,8 +173,38 @@ copy_samples_32 (gint32 * out, ogg_int32_t ** in, guint samples, gint channels)
}
static void
copy_samples_16 (gint16 * out, ogg_int32_t ** in, guint samples, gint channels)
copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
guint samples, gint channels, gint width)
{
gint16 *out = (gint16 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint j;
for (j = 0; j < samples; j++) {
*out++ = CLIP_TO_15 (in[0][j] >> 9);
}
}
static void
copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
guint samples, gint channels, gint width)
{
gint16 *out = (gint16 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint j;
for (j = 0; j < samples; j++) {
*out++ = CLIP_TO_15 (in[0][j] >> 9);
*out++ = CLIP_TO_15 (in[1][j] >> 9);
}
}
static void
copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
gint channels, gint width)
{
gint16 *out = (gint16 *) _out;
ogg_int32_t **in = (ogg_int32_t **) _in;
gint i, j;
for (j = 0; j < samples; j++) {
@ -106,17 +214,39 @@ copy_samples_16 (gint16 * out, ogg_int32_t ** in, guint samples, gint channels)
}
}
void
copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
gint channels, gint width)
CopySampleFunc
get_copy_sample_func (gint channels, gint width)
{
CopySampleFunc f = NULL;
if (width == 4) {
copy_samples_32 ((gint32 *) out, in, samples, channels);
switch (channels) {
case 1:
f = copy_samples_32_m;
break;
case 2:
f = copy_samples_32_s;
break;
default:
f = copy_samples_32;
break;
}
} else if (width == 2) {
copy_samples_16 ((gint16 *) out, in, samples, channels);
switch (channels) {
case 1:
f = copy_samples_16_m;
break;
case 2:
f = copy_samples_16_s;
break;
default:
f = copy_samples_16;
break;
}
} else {
g_assert_not_reached ();
}
return f;
}
#endif

View file

@ -37,8 +37,10 @@ typedef ogg_packet ogg_packet_wrapper;
#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to float audio"
#define GST_VORBIS_DEC_SRC_CAPS \
GST_STATIC_CAPS ("audio/x-raw-float, " "rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, " \
GST_STATIC_CAPS ("audio/x-raw-float, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 256 ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 32")
#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH (32)
@ -91,7 +93,8 @@ struct _ogg_packet_wrapper {
"channels = (int) [ 1, 6 ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) { 16, 32 }, " \
"depth = (int) 16, " "signed = (boolean) true")
"depth = (int) 16, " \
"signed = (boolean) true")
#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH (16)
@ -147,8 +150,9 @@ gst_ogg_packet_from_wrapper (ogg_packet_wrapper * packet)
#endif
void copy_samples (vorbis_sample_t *out, vorbis_sample_t **in,
typedef void (*CopySampleFunc)(vorbis_sample_t *out, vorbis_sample_t **in,
guint samples, gint channels, gint width);
CopySampleFunc get_copy_sample_func (gint channels, gint width);
#endif /* __GST_VORBIS_DEC_LIB_H__ */