bug 1429666 cubeb_resampler_speex: don't call data callback while draining r=padenot

MozReview-Commit-ID: 1XEzZjPGai9

--HG--
extra : rebase_source : 56be87525d46ed3850a15e8e4dd19804dd832408
This commit is contained in:
Karl Tomlinson 2018-01-11 13:30:24 +13:00
parent a331a849a4
commit 88b88a2384
4 changed files with 53 additions and 30 deletions

View File

@ -1,7 +1,11 @@
The source from this directory was copied from the cubeb
git repository using the update.sh script. The only changes
made were those applied by update.sh and the addition of
Makefile.in build files for the Mozilla build system.
made were those applied by update.sh, the addition of
Makefile.in build files for the Mozilla build system,
and the following patches, which may be overwritten when
included upstream.
https://github.com/kinetiknz/cubeb/pull/398/commits/c8e66dee61a35e6a6d54e3630e1668bdbd6984b4
https://github.com/kinetiknz/cubeb/pull/398/commits/2ed979bc891cf1a7822799947a357d4d3b625964
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git

View File

@ -497,13 +497,15 @@ TEST(cubeb, resampler_output_only_noop)
cubeb_resampler_destroy(resampler);
}
long test_drain_data_cb(cubeb_stream * /*stm*/, void * /*user_ptr*/,
long test_drain_data_cb(cubeb_stream * /*stm*/, void * user_ptr,
const void * input_buffer,
void * output_buffer, long frame_count)
{
EXPECT_TRUE(output_buffer);
EXPECT_TRUE(!input_buffer);
return frame_count - 10;
auto cb_count = static_cast<int *>(user_ptr);
(*cb_count)++;
return frame_count - 1;
}
TEST(cubeb, resampler_drain)
@ -515,10 +517,11 @@ TEST(cubeb, resampler_drain)
output_params.channels = 1;
output_params.format = CUBEB_SAMPLE_FLOAT32NE;
target_rate = 48000;
int cb_count = 0;
cubeb_resampler * resampler =
cubeb_resampler_create((cubeb_stream*)nullptr, nullptr, &output_params, target_rate,
test_drain_data_cb, nullptr,
test_drain_data_cb, &cb_count,
CUBEB_RESAMPLER_QUALITY_VOIP);
const long out_frames = 128;
@ -530,9 +533,9 @@ TEST(cubeb, resampler_drain)
out_buffer, out_frames);
} while (got == out_frames);
/* If the above is not an infinite loop, the drain was a success, just mark
* this test as such. */
ASSERT_TRUE(true);
/* The callback should be called once but not again after returning <
* frame_count. */
ASSERT_EQ(cb_count, 1);
cubeb_resampler_destroy(resampler);
}

View File

@ -145,27 +145,33 @@ 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 < 0) {
return got;
if (got < output_frames_before_processing) {
draining = true;
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. */
return output_processor->output(output_buffer, output_frames_needed);
@ -204,11 +210,16 @@ 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;
@ -243,8 +254,12 @@ 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);

View File

@ -62,11 +62,11 @@ public:
: channels(channels)
{}
protected:
size_t frames_to_samples(size_t frames)
size_t frames_to_samples(size_t frames) const
{
return frames * channels;
}
size_t samples_to_frames(size_t samples)
size_t samples_to_frames(size_t samples) const
{
assert(!(samples % channels));
return samples / channels;
@ -157,6 +157,7 @@ private:
cubeb_stream * const stream;
const cubeb_data_callback data_callback;
void * const user_ptr;
bool draining = false;
};
/** Handles one way of a (possibly) duplex resampler, working on interleaved
@ -282,7 +283,7 @@ public:
* exactly `output_frame_count` resampled frames. This can return a number
* slightly bigger than what is strictly necessary, but it guaranteed that the
* number of output frames will be exactly equal. */
uint32_t input_needed_for_output(uint32_t output_frame_count)
uint32_t input_needed_for_output(uint32_t output_frame_count) const
{
int32_t unresampled_frames_left = samples_to_frames(resampling_in_buffer.length());
int32_t resampled_frames_left = samples_to_frames(resampling_out_buffer.length());
@ -461,7 +462,7 @@ public:
* @parameter frames_needed the number of frames one want to write into the
* delay_line
* @returns the number of frames one will get. */
size_t input_needed_for_output(uint32_t frames_needed)
size_t input_needed_for_output(uint32_t frames_needed) const
{
return frames_needed;
}