Bug 1339816 - Update cubeb from upstream to 8977c13b. r=padenot a=needmacnightlyrespin

MozReview-Commit-ID: 942LCa6dOzJ

--HG--
extra : source : 9416a107fa60f31c745acf7821b52cd5a8ef8e98
This commit is contained in:
Alex Chronopoulos 2017-02-17 19:20:34 +02:00
Родитель 59cd73fbfa
Коммит 3d4c312be6
5 изменённых файлов: 78 добавлений и 67 удалений

Просмотреть файл

@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.
The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
The git commit ID used was 21e96ac7fd456dc957cd9947a61da1366a1f862d.
The git commit ID used was 8977c13bf0dab9a7716501ae92ca5945fe4e1dae.

Просмотреть файл

@ -717,7 +717,8 @@ TEST(cubeb, resampler_passthrough_duplex_callback_reordering)
output_seq_idx += BUF_BASE_SIZE;
ASSERT_EQ(prebuffer_frames, static_cast<long>(ARRAY_LENGTH(input_buffer_prebuffer) / input_params.channels));
// prebuffer_frames will hold the frames used by the resampler.
ASSERT_EQ(prebuffer_frames, BUF_BASE_SIZE);
ASSERT_EQ(got, BUF_BASE_SIZE);
for (uint32_t i = 0; i < 300; i++) {

Просмотреть файл

@ -49,6 +49,16 @@ typedef UInt32 AudioFormatFlags;
const char * DISPATCH_QUEUE_LABEL = "org.mozilla.cubeb";
#ifdef ALOGV
#undef ALOGV
#endif
#define ALOGV(msg, ...) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{LOGV(msg, ##__VA_ARGS__);})
#ifdef ALOG
#undef ALOG
#endif
#define ALOG(msg, ...) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{LOG(msg, ##__VA_ARGS__);})
/* Testing empirically, some headsets report a minimal latency that is very
* low, but this does not work in practice. Lie and say the minimum is 256
* frames. */
@ -221,13 +231,17 @@ struct cubeb_stream {
/* Hold the input samples in every
* input callback iteration */
std::unique_ptr<auto_array_wrapper> input_linear_buffer;
// After the resampling some input data remains stored inside
// the resampler. This number is used in order to calculate
// the number of extra silence frames in input.
std::atomic<uint32_t> available_input_frames{ 0 };
/* Frames on input buffer */
std::atomic<uint32_t> input_buffer_frames{ 0 };
/* Frame counters */
std::atomic<uint64_t> frames_played{ 0 };
uint64_t frames_queued = 0;
std::atomic<int64_t> frames_read{ 0 };
std::atomic<bool> shutdown{ false };
std::atomic<bool> shutdown{ true };
std::atomic<bool> draining{ false };
/* Latency requested by the user. */
uint32_t latency_frames = 0;
@ -235,11 +249,6 @@ struct cubeb_stream {
uint64_t hw_latency_frames = UINT64_MAX;
std::atomic<float> panning{ 0 };
std::unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler;
/* This is the number of output callback we got in a row. This is usually one,
* but can be two when the input and output rate are different, and more when
* a device has been plugged or unplugged, as there can be some time before
* the device is ready. */
std::atomic<int> output_callback_in_a_row{ 0 };
/* This is true if a device change callback is currently running. */
std::atomic<bool> switching_device{ false };
std::atomic<bool> buffer_size_change_state{ false };
@ -377,16 +386,18 @@ audiounit_render_input(cubeb_stream * stm,
stm->input_linear_buffer->push(input_buffer_list.mBuffers[0].mData,
input_frames * stm->input_desc.mChannelsPerFrame);
LOGV("(%p) input: buffers %u, size %u, channels %u, frames %d.",
/* Advance input frame counter. */
assert(input_frames > 0);
stm->frames_read += input_frames;
stm->available_input_frames += input_frames;
ALOGV("(%p) input: buffers %u, size %u, channels %u, rendered frames %d, total frames %d.",
stm,
(unsigned int) input_buffer_list.mNumberBuffers,
(unsigned int) input_buffer_list.mBuffers[0].mDataByteSize,
(unsigned int) input_buffer_list.mBuffers[0].mNumberChannels,
(unsigned int) input_frames);
/* Advance input frame counter. */
assert(input_frames > 0);
stm->frames_read += input_frames;
(unsigned int) input_frames,
stm->available_input_frames.load());
return noErr;
}
@ -405,19 +416,10 @@ audiounit_input_callback(void * user_ptr,
assert(AU_IN_BUS == bus);
if (stm->shutdown) {
LOG("(%p) input shutdown", stm);
ALOG("(%p) input shutdown", stm);
return noErr;
}
// This happens when we're finally getting a new input callback after having
// switched device, we can clear the input buffer now, only keeping the data
// we just got.
if (stm->output_callback_in_a_row > stm->expected_output_callbacks_in_a_row) {
stm->input_linear_buffer->pop(
stm->input_linear_buffer->length() -
input_frames * stm->input_stream_params.channels);
}
OSStatus r = audiounit_render_input(stm, flags, tstamp, bus, input_frames);
if (r != noErr) {
return r;
@ -425,7 +427,6 @@ audiounit_input_callback(void * user_ptr,
// Full Duplex. We'll call data_callback in the AudioUnit output callback.
if (stm->output_unit != NULL) {
stm->output_callback_in_a_row = 0;
return noErr;
}
@ -449,6 +450,12 @@ audiounit_input_callback(void * user_ptr,
return noErr;
}
static uint32_t
minimum_resampling_input_frames(cubeb_stream *stm)
{
return ceilf(stm->input_hw_rate / stm->output_hw_rate * stm->input_buffer_frames);
}
static bool
is_extra_input_needed(cubeb_stream * stm)
{
@ -457,17 +464,8 @@ is_extra_input_needed(cubeb_stream * stm)
* Otherwise, if we had more than expected callbacks in a row, or we're currently
* switching, we add some silence as well to compensate for the fact that
* we're lacking some input data. */
/* If resampling is taking place after every output callback
* the input buffer expected to be empty. Any frame left over
* from resampling is stored inside the resampler available to
* be used in next iteration as needed.
* BUT when noop_resampler is operating we have left over
* frames since it does not store anything internally. */
return stm->frames_read == 0 ||
(stm->input_linear_buffer->length() == 0 &&
(stm->output_callback_in_a_row > stm->expected_output_callbacks_in_a_row ||
stm->switching_device));
stm->available_input_frames.load() < minimum_resampling_input_frames(stm);
}
static OSStatus
@ -483,20 +481,19 @@ audiounit_output_callback(void * user_ptr,
cubeb_stream * stm = static_cast<cubeb_stream *>(user_ptr);
stm->output_callback_in_a_row++;
ALOGV("(%p) output: buffers %u, size %u, channels %u, frames %u, total input frames %d.",
stm,
(unsigned int) outBufferList->mNumberBuffers,
(unsigned int) outBufferList->mBuffers[0].mDataByteSize,
(unsigned int) outBufferList->mBuffers[0].mNumberChannels,
(unsigned int) output_frames,
stm->available_input_frames.load());
LOGV("(%p) output: buffers %u, size %u, channels %u, frames %u.",
stm,
(unsigned int) outBufferList->mNumberBuffers,
(unsigned int) outBufferList->mBuffers[0].mDataByteSize,
(unsigned int) outBufferList->mBuffers[0].mNumberChannels,
(unsigned int) output_frames);
long input_frames = 0;
long input_frames = 0, input_frames_before_fill = 0;
void * output_buffer = NULL, * input_buffer = NULL;
if (stm->shutdown) {
LOG("(%p) output shutdown.", stm);
ALOG("(%p) output shutdown.", stm);
audiounit_make_silent(&outBufferList->mBuffers[0]);
return noErr;
}
@ -518,16 +515,19 @@ audiounit_output_callback(void * user_ptr,
/* If Full duplex get also input buffer */
if (stm->input_unit != NULL) {
if (is_extra_input_needed(stm)) {
uint32_t min_input_frames_required = ceilf(stm->input_hw_rate / stm->output_hw_rate *
stm->input_buffer_frames);
stm->input_linear_buffer->push_silence(min_input_frames_required * stm->input_desc.mChannelsPerFrame);
LOG("(%p) %s pushed %u frames of input silence.", stm, stm->frames_read == 0 ? "Input hasn't started," :
stm->switching_device ? "Device switching," : "Drop out,", min_input_frames_required);
uint32_t min_input_frames = minimum_resampling_input_frames(stm);
stm->input_linear_buffer->push_silence(min_input_frames * stm->input_desc.mChannelsPerFrame);
stm->available_input_frames += min_input_frames;
ALOG("(%p) %s pushed %u frames of input silence.", stm, stm->frames_read == 0 ? "Input hasn't started," :
stm->switching_device ? "Device switching," : "Drop out,", min_input_frames);
}
// The input buffer
input_buffer = stm->input_linear_buffer->data();
// Number of input frames in the buffer
// Number of input frames in the buffer. It will change to actually used frames
// inside fill
input_frames = stm->input_linear_buffer->length() / stm->input_desc.mChannelsPerFrame;
// Number of input frames pushed inside resampler.
input_frames_before_fill = input_frames;
}
/* Call user callback through resampler. */
@ -538,7 +538,11 @@ audiounit_output_callback(void * user_ptr,
output_frames);
if (input_buffer) {
stm->input_linear_buffer->pop(input_frames * stm->input_desc.mChannelsPerFrame);
// Decrease counter by the number of frames used by resampler
stm->available_input_frames -= input_frames;
assert(stm->available_input_frames.load() >= 0);
// Pop from the buffer the frames pushed to the resampler.
stm->input_linear_buffer->pop(input_frames_before_fill * stm->input_desc.mChannelsPerFrame);
}
if (outframes < 0) {
@ -714,6 +718,9 @@ audiounit_property_listener_callback(AudioObjectID /* id */, UInt32 address_coun
case kAudioDevicePropertyDataSource:
LOG("Event[%u] - mSelector == kAudioHardwarePropertyDataSource", (unsigned int) i);
break;
default:
LOG("Event[%u] - mSelector == Unexpected Event id %d, return", (unsigned int) i, addresses[i].mSelector);
return noErr;
}
}
@ -890,6 +897,16 @@ audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
if (r != noErr) {
return CUBEB_ERROR;
}
/* Event to notify when the input is going away. */
AudioDeviceID dev = stm->input_device ? stm->input_device :
audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
r = audiounit_remove_listener(stm, dev, kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
if (r != noErr) {
PRINT_ERROR_CODE("AudioObjectRemovePropertyListener/input/kAudioDevicePropertyDeviceIsAlive", r);
return CUBEB_ERROR;
}
}
return CUBEB_OK;
}
@ -1301,18 +1318,8 @@ audiounit_init_input_linear_buffer(cubeb_stream * stream, uint32_t capacity)
} else {
stream->input_linear_buffer.reset(new auto_array_wrapper_impl<float>(size));
}
assert(stream->input_linear_buffer->length() == 0);
// Pre-buffer silence if needed
if (capacity != 1) {
size_t silence_size = stream->input_buffer_frames *
stream->input_desc.mChannelsPerFrame;
stream->input_linear_buffer->push_silence(silence_size);
assert(stream->input_linear_buffer->length() == silence_size);
}
return CUBEB_OK;
}

Просмотреть файл

@ -72,6 +72,7 @@ long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_cou
if (input_buffer) {
internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
*input_frames_count = output_frames;
}
return rv;
@ -179,7 +180,7 @@ 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);
resampled_input = input_processor->output(resampled_frame_count, (size_t*)input_frames_count);
long got = data_callback(stream, user_ptr,
resampled_input, nullptr, resampled_frame_count);
@ -226,7 +227,7 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
* callback. */
input_processor->input(in_buffer, *input_frames_count);
resampled_input =
input_processor->output(output_frames_before_processing);
input_processor->output(output_frames_before_processing, (size_t*)input_frames_count);
} else {
resampled_input = nullptr;
}

Просмотреть файл

@ -222,7 +222,7 @@ public:
/** Returns a buffer containing exactly `output_frame_count` resampled frames.
* The consumer should not hold onto the pointer. */
T * output(size_t output_frame_count)
T * output(size_t output_frame_count, size_t * input_frames_used)
{
if (resampling_out_buffer.capacity() < frames_to_samples(output_frame_count)) {
resampling_out_buffer.reserve(frames_to_samples(output_frame_count));
@ -239,6 +239,7 @@ public:
/* This shifts back any unresampled samples to the beginning of the input
buffer. */
resampling_in_buffer.pop(nullptr, frames_to_samples(in_len));
*input_frames_used = in_len;
return resampling_out_buffer.data();
}
@ -376,7 +377,7 @@ public:
* @parameter frames_needed the number of frames to be returned.
* @return a buffer containing the delayed frames. The consumer should not
* hold onto the pointer. */
T * output(uint32_t frames_needed)
T * output(uint32_t frames_needed, size_t * input_frames_used)
{
if (delay_output_buffer.capacity() < frames_to_samples(frames_needed)) {
delay_output_buffer.reserve(frames_to_samples(frames_needed));
@ -386,6 +387,7 @@ public:
delay_output_buffer.push(delay_input_buffer.data(),
frames_to_samples(frames_needed));
delay_input_buffer.pop(nullptr, frames_to_samples(frames_needed));
*input_frames_used = frames_needed;
return delay_output_buffer.data();
}