diff options
Diffstat (limited to 'src/pulsecore/sink-input.c')
-rw-r--r-- | src/pulsecore/sink-input.c | 88 |
1 files changed, 66 insertions, 22 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d27f00f0..db98dd54 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -341,7 +341,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) /* } */ if (!i->thread_info.resampler) { - do_volume_adj_here = 0; + do_volume_adj_here = 0; /* FIXME??? */ ret = i->peek(i, chunk); goto finish; } @@ -356,15 +356,14 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) if ((ret = i->peek(i, &tchunk)) < 0) goto finish; - pa_assert(tchunk.length); + pa_assert(tchunk.length > 0); l = pa_resampler_request(i->thread_info.resampler, CONVERT_BUFFER_LENGTH); - if (l > tchunk.length) - l = tchunk.length; + if (tchunk.length > l) + tchunk.length = l; - i->drop(i, &tchunk, l); - tchunk.length = l; + i->drop(i, tchunk.length); /* It might be necessary to adjust the volume here */ if (do_volume_adj_here && !volume_is_norm) { @@ -377,7 +376,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) } pa_assert(i->thread_info.resampled_chunk.memblock); - pa_assert(i->thread_info.resampled_chunk.length); + pa_assert(i->thread_info.resampled_chunk.length > 0); *chunk = i->thread_info.resampled_chunk; pa_memblock_ref(i->thread_info.resampled_chunk.memblock); @@ -409,7 +408,7 @@ finish: return ret; } -void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) { +void pa_sink_input_drop(pa_sink_input *i, size_t length) { pa_sink_input_assert_ref(i); pa_assert(length > 0); @@ -440,22 +439,67 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt /* return; */ /* } */ - if (!i->thread_info.resampler) { - if (i->drop) - i->drop(i, chunk, length); - return; - } - - pa_assert(i->thread_info.resampled_chunk.memblock); - pa_assert(i->thread_info.resampled_chunk.length >= length); + pa_log("dropping %u", length); + + if (i->thread_info.resampled_chunk.memblock) { + size_t l = length; + + if (l > i->thread_info.resampled_chunk.length) + l = i->thread_info.resampled_chunk.length; + + pa_log("really dropping %u", l); + + i->thread_info.resampled_chunk.index += l; + i->thread_info.resampled_chunk.length -= l; + + if (i->thread_info.resampled_chunk.length <= 0) { + pa_memblock_unref(i->thread_info.resampled_chunk.memblock); + pa_memchunk_reset(&i->thread_info.resampled_chunk); + } - i->thread_info.resampled_chunk.index += length; - i->thread_info.resampled_chunk.length -= length; + length -= l; + } - if (i->thread_info.resampled_chunk.length <= 0) { - pa_memblock_unref(i->thread_info.resampled_chunk.memblock); - i->thread_info.resampled_chunk.memblock = NULL; - i->thread_info.resampled_chunk.index = i->thread_info.resampled_chunk.length = 0; + pa_log("really remaining %u", length); + + if (length > 0) { + + if (i->thread_info.resampler) { + /* So, we have a resampler. To avoid discontinuities we + * have to actually read all data that could be read and + * pass it through the resampler. */ + + while (length > 0) { + pa_memchunk chunk; + pa_cvolume volume; + + if (pa_sink_input_peek(i, &chunk, &volume) >= 0) { + size_t l = chunk.length; + + if (l > length) + l = length; + + pa_sink_input_drop(i, l); + length -= l; + + } else { + /* Hmmm, peeking failed, so let's at least drop + * the right amount of data */ + + if (i->drop) + i->drop(i, pa_resampler_request(i->thread_info.resampler, length)); + + break; + } + } + + } else { + + /* We have no resampler, hence let's just drop the data */ + + if (i->drop) + i->drop(i, length); + } } } |