mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-22 07:08:23 +00:00
gst/audioresample/: add room for extra overlap samples when asked to transform size protect against possible mem corr...
Original commit message from CVS: * gst/audioresample/debug.c: * gst/audioresample/gstaudioresample.c: add room for extra overlap samples when asked to transform size protect against possible mem corruption and check for discrepancies between written size and outbuffer's size so we can warn for potential problems * gst/audioresample/resample.c: (resample_init), (resample_get_output_size_for_input), (resample_get_output_size), (resample_set_n_channels), (resample_set_format): set debug level based on RESAMPLE_DEBUG env var make sure that get_output_size* returns a whole number of sample_size set sample_size each time either channel or format is set * gst/audioresample/resample_chunk.c: (resample_scale_chunk): * gst/audioresample/resample_functable.c: (resample_scale_functable): * gst/audioresample/resample_ref.c: (resample_scale_ref): remove r->sample_size, it's done in resample.c now add some debugging to the ref implementation make sure we only give back bytes that are wholes of the sample size
This commit is contained in:
parent
2a13ddfd65
commit
7647f7fc4e
7 changed files with 110 additions and 36 deletions
38
ChangeLog
38
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
2005-08-25 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* gst/audioresample/debug.c:
|
||||
* gst/audioresample/gstaudioresample.c:
|
||||
add room for extra overlap samples when asked to transform size
|
||||
protect against possible mem corruption and check for discrepancies
|
||||
between written size and outbuffer's size so we can warn for
|
||||
potential problems
|
||||
* gst/audioresample/resample.c: (resample_init),
|
||||
(resample_get_output_size_for_input), (resample_get_output_size),
|
||||
(resample_set_n_channels), (resample_set_format):
|
||||
set debug level based on RESAMPLE_DEBUG env var
|
||||
make sure that get_output_size* returns a whole number of
|
||||
sample_size
|
||||
set sample_size each time either channel or format is set
|
||||
* gst/audioresample/resample_chunk.c: (resample_scale_chunk):
|
||||
* gst/audioresample/resample_functable.c:
|
||||
(resample_scale_functable):
|
||||
* gst/audioresample/resample_ref.c: (resample_scale_ref):
|
||||
remove r->sample_size, it's done in resample.c now
|
||||
add some debugging to the ref implementation
|
||||
make sure we only give back bytes that are wholes of the sample
|
||||
size
|
||||
|
||||
2005-08-25 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
* gst/playback/gstplaybasebin.c: (fill_buffer):
|
||||
Revert unpopular change for GST_MESSAGE_SRC to GObject.
|
||||
|
@ -5,7 +29,7 @@
|
|||
2005-08-25 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* gst/volume/gstvolume.c:
|
||||
made set_caps function static
|
||||
made set_caps function static
|
||||
|
||||
2005-08-24 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
|
@ -44,6 +68,18 @@
|
|||
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times):
|
||||
Basesink does newsegment calculations for us now.
|
||||
|
||||
2005-08-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* check/Makefile.am:
|
||||
* configure.ac:
|
||||
add core's plugins to the mix so that playbin works
|
||||
* check/generic/states.c: (GST_START_TEST):
|
||||
set a 0 timeout on pipelines, so they don't force the next
|
||||
state change
|
||||
* gst/playback/gstplaybasebin.c: (setup_source), (prepare_output),
|
||||
(gst_play_base_bin_change_state):
|
||||
remove the crappy error handling and do GST error handling
|
||||
|
||||
2005-08-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* check/Makefile.am:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 bastard ! you only gave me %d bytes, not %d",
|
||||
"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'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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue