diff options
-rw-r--r-- | gst/audioresample/debug.c | 2 | ||||
-rw-r--r-- | gst/audioresample/gstaudioresample.c | 70 | ||||
-rw-r--r-- | gst/audioresample/resample.c | 23 | ||||
-rw-r--r-- | gst/audioresample/resample_chunk.c | 1 | ||||
-rw-r--r-- | gst/audioresample/resample_functable.c | 1 | ||||
-rw-r--r-- | gst/audioresample/resample_ref.c | 11 |
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; } - } |