summaryrefslogtreecommitdiffstats
path: root/media/libcubeb/src/cubeb_resampler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libcubeb/src/cubeb_resampler.cpp')
-rw-r--r--media/libcubeb/src/cubeb_resampler.cpp122
1 files changed, 86 insertions, 36 deletions
diff --git a/media/libcubeb/src/cubeb_resampler.cpp b/media/libcubeb/src/cubeb_resampler.cpp
index f6676946c..2bc889340 100644
--- a/media/libcubeb/src/cubeb_resampler.cpp
+++ b/media/libcubeb/src/cubeb_resampler.cpp
@@ -35,29 +35,54 @@ to_speex_quality(cubeb_resampler_quality q)
}
}
-long noop_resampler::fill(void * input_buffer, long * input_frames_count,
- void * output_buffer, long output_frames)
+uint32_t min_buffered_audio_frame(uint32_t sample_rate)
+{
+ return sample_rate / 20;
+}
+
+template<typename T>
+passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s,
+ cubeb_data_callback cb,
+ void * ptr,
+ uint32_t input_channels,
+ uint32_t sample_rate)
+ : processor(input_channels)
+ , stream(s)
+ , data_callback(cb)
+ , user_ptr(ptr)
+ , sample_rate(sample_rate)
+{
+}
+
+template<typename T>
+long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_count,
+ void * output_buffer, long output_frames)
{
if (input_buffer) {
assert(input_frames_count);
}
- assert((input_buffer && output_buffer &&
- *input_frames_count >= output_frames) ||
- (!input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
- (!output_buffer && output_frames == 0));
-
- if (output_buffer == nullptr) {
- assert(input_buffer);
- output_frames = *input_frames_count;
+ assert((input_buffer && output_buffer) ||
+ (output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
+ (input_buffer && !output_buffer && output_frames == 0));
+
+ if (input_buffer) {
+ if (!output_buffer) {
+ output_frames = *input_frames_count;
+ }
+ internal_input_buffer.push(static_cast<T*>(input_buffer),
+ frames_to_samples(*input_frames_count));
}
- if (input_buffer && *input_frames_count != output_frames) {
- assert(*input_frames_count > output_frames);
+ long rv = data_callback(stream, user_ptr, internal_input_buffer.data(),
+ output_buffer, output_frames);
+
+ if (input_buffer) {
+ internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
*input_frames_count = output_frames;
+ drop_audio_if_needed();
}
- return data_callback(stream, user_ptr,
- input_buffer, output_buffer, output_frames);
+ return rv;
}
template<typename T, typename InputProcessor, typename OutputProcessor>
@@ -120,27 +145,32 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
assert(!input_buffer && (!input_frames_count || *input_frames_count == 0) &&
output_buffer && output_frames_needed);
- long got = 0;
- T * out_unprocessed = nullptr;
- long output_frames_before_processing = 0;
+ if (!draining) {
+ long got = 0;
+ T * out_unprocessed = nullptr;
+ long output_frames_before_processing = 0;
+ /* fill directly the input buffer of the output processor to save a copy */
+ output_frames_before_processing =
+ output_processor->input_needed_for_output(output_frames_needed);
- /* fill directly the input buffer of the output processor to save a copy */
- output_frames_before_processing =
- output_processor->input_needed_for_output(output_frames_needed);
+ out_unprocessed =
+ output_processor->input_buffer(output_frames_before_processing);
- out_unprocessed =
- output_processor->input_buffer(output_frames_before_processing);
+ got = data_callback(stream, user_ptr,
+ nullptr, out_unprocessed,
+ output_frames_before_processing);
- got = data_callback(stream, user_ptr,
- nullptr, out_unprocessed,
- output_frames_before_processing);
+ if (got < output_frames_before_processing) {
+ draining = true;
- if (got < 0) {
- return got;
- }
+ if (got < 0) {
+ return got;
+ }
+ }
- output_processor->written(got);
+ output_processor->written(got);
+ }
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */
@@ -163,7 +193,10 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
/* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(input_buffer, *input_frames_count);
- resampled_input = input_processor->output(resampled_frame_count);
+
+ size_t frames_resampled = 0;
+ resampled_input = input_processor->output(resampled_frame_count, &frames_resampled);
+ *input_frames_count = frames_resampled;
long got = data_callback(stream, user_ptr,
resampled_input, nullptr, resampled_frame_count);
@@ -174,18 +207,22 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
return (*input_frames_count) * (got / resampled_frame_count);
}
-
template<typename T, typename InputProcessor, typename OutputProcessor>
long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
::fill_internal_duplex(T * in_buffer, long * input_frames_count,
T * out_buffer, long output_frames_needed)
{
+ if (draining) {
+ // discard input and drain any signal remaining in the resampler.
+ return output_processor->output(out_buffer, output_frames_needed);
+ }
+
/* The input data, after eventual resampling. This is passed to the callback. */
T * resampled_input = nullptr;
/* The output buffer passed down in the callback, that might be resampled. */
T * out_unprocessed = nullptr;
- size_t output_frames_before_processing = 0;
+ long output_frames_before_processing = 0;
/* The number of frames returned from the callback. */
long got = 0;
@@ -210,8 +247,11 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
/* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(in_buffer, *input_frames_count);
+
+ size_t frames_resampled = 0;
resampled_input =
- input_processor->output(output_frames_before_processing);
+ input_processor->output(output_frames_before_processing, &frames_resampled);
+ *input_frames_count = frames_resampled;
} else {
resampled_input = nullptr;
}
@@ -220,15 +260,25 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
resampled_input, out_unprocessed,
output_frames_before_processing);
- if (got < 0) {
- return got;
+ if (got < output_frames_before_processing) {
+ draining = true;
+
+ if (got < 0) {
+ return got;
+ }
}
output_processor->written(got);
+ input_processor->drop_audio_if_needed();
+
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */
- return output_processor->output(out_buffer, output_frames_needed);
+ got = output_processor->output(out_buffer, output_frames_needed);
+
+ output_processor->drop_audio_if_needed();
+
+ return got;
}
/* Resampler C API */