summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gst/audioresample/debug.c2
-rw-r--r--gst/audioresample/gstaudioresample.c70
-rw-r--r--gst/audioresample/resample.c23
-rw-r--r--gst/audioresample/resample_chunk.c1
-rw-r--r--gst/audioresample/resample_functable.c1
-rw-r--r--gst/audioresample/resample_ref.c11
6 files changed, 73 insertions, 35 deletions
diff --git a/gst/audioresample/debug.c b/gst/audioresample/debug.c
index 11fb8842..27877277 100644
--- a/gst/audioresample/debug.c
+++ b/gst/audioresample/debug.c
@@ -16,7 +16,7 @@ static const char *resample_debug_level_names[] = {
"LOG"
};
-static int resample_debug_level = RESAMPLE_LEVEL_LOG;
+static int resample_debug_level = RESAMPLE_LEVEL_ERROR;
void
resample_debug_log (int level, const char *file, const char *function,
diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c
index f2549b28..2aba0928 100644
--- a/gst/audioresample/gstaudioresample.c
+++ b/gst/audioresample/gstaudioresample.c
@@ -55,14 +55,15 @@ enum
};
#define SUPPORTED_CAPS \
- GST_STATIC_CAPS (\
+GST_STATIC_CAPS ( \
"audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 16, " \
"depth = (int) 16, " \
- "signed = (boolean) true")
+ "signed = (boolean) true " \
+)
#if 0
/* disabled because it segfaults */
@@ -255,18 +256,18 @@ static gboolean
return TRUE;
}
-gboolean audioresample_transform_size (GstBaseTransform * base,
+gboolean
+ audioresample_transform_size (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
- guint * othersize)
-{
+ guint * othersize) {
GstAudioresample *audioresample = GST_AUDIORESAMPLE (base);
ResampleState *state;
GstCaps *srccaps, *sinkcaps;
gboolean use_internal = FALSE; /* whether we use the internal state */
gboolean ret = TRUE;
- /* FIXME: make sure incaps/outcaps get renamed to caps/othercaps, since
- * interpretation depends on the direction */
+ GST_DEBUG_OBJECT (base, "asked to transform size %d in direction %s",
+ size, direction == GST_PAD_SINK ? "SINK" : "SRC");
if (direction == GST_PAD_SINK) {
sinkcaps = caps;
srccaps = othercaps;
@@ -282,11 +283,12 @@ gboolean audioresample_transform_size (GstBaseTransform * base,
use_internal = TRUE;
state = audioresample->resample;
} else {
+ GST_DEBUG_OBJECT (audioresample,
+ "caps are not the set caps, creating state");
state = resample_new ();
resample_set_state_from_caps (state, sinkcaps, srccaps, NULL, NULL, NULL);
}
- /* we can use our own state to answer the question */
if (direction == GST_PAD_SINK) {
/* asked to convert size of an incoming buffer */
*othersize = resample_get_output_size_for_input (state, size);
@@ -294,6 +296,11 @@ gboolean audioresample_transform_size (GstBaseTransform * base,
/* take a best guess, this is called cheating */
*othersize = floor (size * state->i_rate / state->o_rate);
}
+ *othersize += state->sample_size;
+
+ /* we make room for one extra sample, given that the resampling filter
+ * can output an extra one for non-integral i_rate/o_rate */
+ GST_DEBUG_OBJECT (base, "transformed size %d to %d", size, *othersize);
if (!use_internal) {
resample_free (state);
@@ -302,9 +309,9 @@ gboolean audioresample_transform_size (GstBaseTransform * base,
return ret;
}
-gboolean audioresample_set_caps (GstBaseTransform * base, GstCaps * incaps,
- GstCaps * outcaps)
-{
+gboolean
+ audioresample_set_caps (GstBaseTransform * base, GstCaps * incaps,
+ GstCaps * outcaps) {
gboolean ret;
gint inrate, outrate;
int channels;
@@ -365,32 +372,45 @@ static GstFlowReturn
resample_add_input_data (r, data, size, NULL, NULL);
outsize = resample_get_output_size (r);
- if (outsize != GST_BUFFER_SIZE (outbuf)) {
+ GST_DEBUG_OBJECT (audioresample, "audioresample can give me %d bytes",
+ outsize);
+
+ /* protect against mem corruption */
+ if (outsize > GST_BUFFER_SIZE (outbuf)) {
GST_WARNING_OBJECT (audioresample,
"overriding audioresample's outsize %d with outbuffer's size %d",
outsize, GST_BUFFER_SIZE (outbuf));
outsize = GST_BUFFER_SIZE (outbuf);
}
+ /* catch possibly wrong size differences */
+ if (GST_BUFFER_SIZE (outbuf) - outsize > r->sample_size) {
+ GST_WARNING_OBJECT (audioresample,
+ "audioresample's outsize %d too far from outbuffer's size %d",
+ outsize, GST_BUFFER_SIZE (outbuf));
+ }
outsize = resample_get_output_data (r, GST_BUFFER_DATA (outbuf), outsize);
GST_BUFFER_TIMESTAMP (outbuf) =
audioresample->offset * GST_SECOND / audioresample->o_rate;
audioresample->offset += outsize / sizeof (gint16) / audioresample->channels;
+ GST_BUFFER_DURATION (outbuf) = outsize * GST_SECOND / audioresample->o_rate;
- if (outsize != GST_BUFFER_SIZE (outbuf)) {
+ /* check for possible mem corruption */
+ if (outsize > GST_BUFFER_SIZE (outbuf)) {
+ /* this is an error that when it happens, would need fixing in the
+ * resample library; we told
+ * it we wanted only GST_BUFFER_SIZE (outbuf), and it gave us more ! */
+ GST_WARNING_OBJECT (audioresample,
+ "audioresample, you memory corrupting bastard. "
+ "you gave me outsize %d while my buffer was size %d",
+ outsize, GST_BUFFER_SIZE (outbuf));
+ return GST_FLOW_ERROR;
+ }
+ /* catch possibly wrong size differences */
+ if (GST_BUFFER_SIZE (outbuf) - outsize > r->sample_size) {
GST_WARNING_OBJECT (audioresample,
- "audioresample, you bastard ! you only gave me %d bytes, not %d",
+ "audioresample's written outsize %d too far from outbuffer's size %d",
outsize, GST_BUFFER_SIZE (outbuf));
- /* if the size we get is smaller than the buffer, it's still fine; we
- * just waste a bit of space on the end */
- if (outsize < GST_BUFFER_SIZE (outbuf)) {
- GST_BUFFER_SIZE (outbuf) = outsize;
- return GST_FLOW_OK;
- } else {
- /* this is an error that needs fixing in the resample library; we told
- * it we wanted only GST_BUFFER_SIZE (outbuf), and it gave us more ! */
- return GST_FLOW_ERROR;
- }
}
return GST_FLOW_OK;
@@ -408,7 +428,7 @@ static void
switch (prop_id) {
case ARG_FILTERLEN:
audioresample->filter_length = g_value_get_int (value);
- GST_DEBUG_OBJECT (GST_ELEMENT (audioresample), "new filter length %d\n",
+ GST_DEBUG_OBJECT (GST_ELEMENT (audioresample), "new filter length %d",
audioresample->filter_length);
resample_set_filter_length (audioresample->resample,
audioresample->filter_length);
diff --git a/gst/audioresample/resample.c b/gst/audioresample/resample.c
index e8ec45fb..8e759da2 100644
--- a/gst/audioresample/resample.c
+++ b/gst/audioresample/resample.c
@@ -42,11 +42,16 @@ void
resample_init (void)
{
static int inited = 0;
+ const char *debug;
if (!inited) {
oil_init ();
inited = 1;
}
+
+ if ((debug = g_getenv ("RESAMPLE_DEBUG"))) {
+ resample_debug_set_level (atoi (debug));
+ }
}
ResampleState *
@@ -141,14 +146,24 @@ resample_input_eos (ResampleState * r)
int
resample_get_output_size_for_input (ResampleState * r, int size)
{
- return floor (size * r->o_rate / r->i_rate);
+ int outsize;
+ double outd;
+
+ g_return_val_if_fail (r->sample_size != 0, 0);
+
+ RESAMPLE_DEBUG ("size %d, o_rate %f, i_rate %f", size, r->o_rate, r->i_rate);
+ outd = (double) size / r->i_rate * r->o_rate;
+ outsize = (int) floor (outd);
+
+ /* round off for sample size */
+ return outsize - (outsize % r->sample_size);
}
int
resample_get_output_size (ResampleState * r)
{
- return floor (audioresample_buffer_queue_get_depth (r->queue) * r->o_rate /
- r->i_rate);
+ return resample_get_output_size_for_input (r,
+ audioresample_buffer_queue_get_depth (r->queue));
}
int
@@ -196,6 +211,7 @@ void
resample_set_n_channels (ResampleState * r, int n_channels)
{
r->n_channels = n_channels;
+ r->sample_size = r->n_channels * resample_format_size (r->format);
r->need_reinit = 1;
}
@@ -203,6 +219,7 @@ void
resample_set_format (ResampleState * r, ResampleFormat format)
{
r->format = format;
+ r->sample_size = r->n_channels * resample_format_size (r->format);
r->need_reinit = 1;
}
diff --git a/gst/audioresample/resample_chunk.c b/gst/audioresample/resample_chunk.c
index c91e1f2a..1cf9f09f 100644
--- a/gst/audioresample/resample_chunk.c
+++ b/gst/audioresample/resample_chunk.c
@@ -56,7 +56,6 @@ void
resample_scale_chunk (ResampleState * r)
{
if (r->need_reinit) {
- r->sample_size = r->n_channels * resample_format_size (r->format);
RESAMPLE_DEBUG ("sample size %d", r->sample_size);
if (r->buffer)
diff --git a/gst/audioresample/resample_functable.c b/gst/audioresample/resample_functable.c
index 7db06ff8..af124276 100644
--- a/gst/audioresample/resample_functable.c
+++ b/gst/audioresample/resample_functable.c
@@ -109,7 +109,6 @@ resample_scale_functable (ResampleState * r)
if (r->need_reinit) {
double hanning_width;
- r->sample_size = r->n_channels * resample_format_size (r->format);
RESAMPLE_DEBUG ("sample size %d", r->sample_size);
if (r->buffer)
diff --git a/gst/audioresample/resample_ref.c b/gst/audioresample/resample_ref.c
index 6717aa23..3fc9d2e8 100644
--- a/gst/audioresample/resample_ref.c
+++ b/gst/audioresample/resample_ref.c
@@ -56,7 +56,6 @@ void
resample_scale_ref (ResampleState * r)
{
if (r->need_reinit) {
- r->sample_size = r->n_channels * resample_format_size (r->format);
RESAMPLE_DEBUG ("sample size %d", r->sample_size);
if (r->buffer)
@@ -88,19 +87,24 @@ resample_scale_ref (ResampleState * r)
#endif
}
- while (r->o_size > 0) {
+ RESAMPLE_DEBUG ("asked to resample %d bytes", r->o_size);
+
+ while (r->o_size >= r->sample_size) {
double midpoint;
int i;
int j;
- RESAMPLE_DEBUG ("i_start %g", r->i_start);
midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
+ RESAMPLE_DEBUG ("still need to output %d bytes, i_start %g, midpoint %f",
+ r->o_size, r->i_start, midpoint);
if (midpoint > 0.5 * r->i_inc) {
RESAMPLE_ERROR ("inconsistent state");
}
while (midpoint < -0.5 * r->i_inc) {
AudioresampleBuffer *buffer;
+ RESAMPLE_DEBUG ("midpoint %f < %f, r->i_inc %f", midpoint,
+ -0.5 * r->i_inc, r->i_inc);
buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
if (buffer == NULL) {
RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
@@ -206,5 +210,4 @@ resample_scale_ref (ResampleState * r)
r->o_buf += r->sample_size;
r->o_size -= r->sample_size;
}
-
}