diff --git a/media/libcubeb/moz.yaml b/media/libcubeb/moz.yaml index dc9b2126ddb2..fa43dab65f63 100644 --- a/media/libcubeb/moz.yaml +++ b/media/libcubeb/moz.yaml @@ -19,5 +19,5 @@ origin: license: "ISC" # update.sh will update this value - release: "5ebe69cb3a1c7b022af85c04187456948b209d4b (2021-05-25 08:15:25 +1200)" + release: "b2f60c983df34f8cac0e061ef32da531c6d82536 (2021-07-13 13:51:30 +0200)" diff --git a/media/libcubeb/src/cubeb_resampler.cpp b/media/libcubeb/src/cubeb_resampler.cpp index 29ad7365fea5..b7bddfea4fe1 100644 --- a/media/libcubeb/src/cubeb_resampler.cpp +++ b/media/libcubeb/src/cubeb_resampler.cpp @@ -222,6 +222,12 @@ cubeb_resampler_speex * callback. */ input_processor->input(input_buffer, *input_frames_count); + /* resampled_frame_count == 0 happens if the resampler + * doesn't have enough input frames buffered to produce 1 resampled frame. */ + if (resampled_frame_count == 0) { + return *input_frames_count; + } + size_t frames_resampled = 0; resampled_input = input_processor->output(resampled_frame_count, &frames_resampled); *input_frames_count = frames_resampled; diff --git a/media/libcubeb/src/cubeb_sndio.c b/media/libcubeb/src/cubeb_sndio.c index dfa413704d11..93af1d2ed308 100644 --- a/media/libcubeb/src/cubeb_sndio.c +++ b/media/libcubeb/src/cubeb_sndio.c @@ -626,7 +626,7 @@ sndio_enumerate_devices(cubeb *context, cubeb_device_type type, device->preferred = CUBEB_DEVICE_PREF_ALL; device->format = CUBEB_DEVICE_FMT_S16NE; device->default_format = CUBEB_DEVICE_FMT_S16NE; - device->max_channels = 16; + device->max_channels = (type == CUBEB_DEVICE_TYPE_INPUT) ? 2 : 8; device->default_rate = 48000; device->min_rate = 4000; device->max_rate = 192000; diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp index 272793ea2554..da0fd98642e6 100644 --- a/media/libcubeb/src/cubeb_wasapi.cpp +++ b/media/libcubeb/src/cubeb_wasapi.cpp @@ -353,6 +353,11 @@ struct cubeb_stream { /* This needs an active audio input stream to be known, and is updated in the * first audio input callback. */ std::atomic input_latency_hns { LATENCY_NOT_AVAILABLE_YET }; + + /* Those attributes count the number of frames requested (resp. received) by + the OS, to be able to detect drifts. This is only used for logging for now. */ + size_t total_input_frames = 0; + size_t total_output_frames = 0; }; class monitor_device_notifications { @@ -908,8 +913,7 @@ int trigger_async_reconfigure(cubeb_stream * stm) /* This helper grabs all the frames available from a capture client, put them in - * linear_input_buffer. linear_input_buffer should be cleared before the - * callback exits. This helper does not work with exclusive mode streams. */ + * the linear_input_buffer. This helper does not work with exclusive mode streams. */ bool get_input_buffer(cubeb_stream * stm) { XASSERT(has_input(stm)); @@ -967,6 +971,8 @@ bool get_input_buffer(cubeb_stream * stm) } } + stm->total_input_frames += frames; + UINT32 input_stream_samples = frames * stm->input_stream_params.channels; // We do not explicitly handle the AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY // flag. There a two primary (non exhaustive) scenarios we anticipate this @@ -1018,6 +1024,8 @@ bool get_input_buffer(cubeb_stream * stm) offset += input_stream_samples; } + ALOGV("get_input_buffer: got %d frames", offset); + XASSERT(stm->linear_input_buffer->length() >= offset); return true; @@ -1086,9 +1094,11 @@ refill_callback_duplex(cubeb_stream * stm) XASSERT(has_input(stm) && has_output(stm)); - rv = get_input_buffer(stm); - if (!rv) { - return rv; + if (stm->input_stream_params.prefs & CUBEB_STREAM_PREF_LOOPBACK) { + HRESULT rv = get_input_buffer(stm); + if (FAILED(rv)) { + return rv; + } } input_frames = stm->linear_input_buffer->length() / stm->input_stream_params.channels; @@ -1110,6 +1120,13 @@ refill_callback_duplex(cubeb_stream * stm) return false; } + stm->total_output_frames += output_frames; + + ALOGV("in: %zu, out: %zu, missing: %ld, ratio: %f", + stm->total_input_frames, stm->total_output_frames, + static_cast(stm->total_output_frames) - stm->total_input_frames, + static_cast(stm->total_output_frames) / stm->total_input_frames); + if (stm->has_dummy_output) { ALOGV("Duplex callback (dummy output): input frames: %Iu, output frames: %Iu", input_frames, output_frames); @@ -1351,10 +1368,18 @@ wasapi_stream_render_loop(LPVOID stream) (!has_input(stm) && has_output(stm))); is_playing = stm->refill_callback(stm); break; - case WAIT_OBJECT_0 + 3: /* input available */ - if (has_input(stm) && has_output(stm)) { continue; } - is_playing = stm->refill_callback(stm); + case WAIT_OBJECT_0 + 3: { /* input available */ + HRESULT rv = get_input_buffer(stm); + if (FAILED(rv)) { + return rv; + } + + if (!has_output(stm)) { + is_playing = stm->refill_callback(stm); + } + break; + } case WAIT_TIMEOUT: XASSERT(stm->shutdown_event == wait_array[0]); if (++timeout_count >= timeout_limit) { @@ -1734,11 +1759,12 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten synchronizing the stream and the engine. http://msdn.microsoft.com/en-us/library/windows/desktop/dd370871%28v=vs.85%29.aspx */ - #ifdef _WIN32_WINNT_WIN10 - *latency_frames = hns_to_frames(params.rate, minimum_period); - #else + // #ifdef _WIN32_WINNT_WIN10 + #if 0 + *latency_frames = hns_to_frames(params.rate, minimum_period); + #else *latency_frames = hns_to_frames(params.rate, default_period); - #endif + #endif LOG("Minimum latency in frames: %u", *latency_frames); @@ -2138,22 +2164,18 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, if (rv == CUBEB_OK) { const char* HANDSFREE_TAG = "BTHHFENUM"; size_t len = sizeof(HANDSFREE_TAG); - if (direction == eCapture && - strlen(device_info.group_id) >= len && - strncmp(device_info.group_id, HANDSFREE_TAG, len) == 0) { - // Rather high-latency to prevent constant under-runs in this particular - // case of an input device using bluetooth handsfree. + if (direction == eCapture) { uint32_t default_period_frames = hns_to_frames(device_info.default_rate, default_period); - latency_frames = default_period_frames * 4; - stm->input_bluetooth_handsfree = true; - LOG("Input is a bluetooth device in handsfree, latency increased to %u frames from a default of %u", latency_frames, default_period_frames); - } else { - uint32_t minimum_period_frames = hns_to_frames(device_info.default_rate, minimum_period); - latency_frames = std::max(latency_frames, minimum_period_frames); - stm->input_bluetooth_handsfree = false; - LOG("Input is a not bluetooth handsfree, latency %s to %u frames (minimum %u)", latency_frames < minimum_period_frames ? "increased" : "set", latency_frames, minimum_period_frames); + if (strlen(device_info.group_id) >= len && + strncmp(device_info.group_id, HANDSFREE_TAG, len) == 0) { + stm->input_bluetooth_handsfree = true; + } else { + stm->input_bluetooth_handsfree = false; + } + // This multiplicator has been found empirically. + latency_frames = default_period_frames * 8; + LOG("Input: latency increased to %u frames from a default of %u", latency_frames, default_period_frames); } - latency_hns = frames_to_hns(device_info.default_rate, latency_frames); wasapi_destroy_device(&device_info); @@ -2196,6 +2218,8 @@ int setup_wasapi_stream_one_side(cubeb_stream * stm, return CUBEB_ERROR; } + LOG("Buffer size is: %d for %s\n", *buffer_frame_count, DIRECTION_NAME); + // Events are used if not looping back if (!is_loopback) { hr = audio_client->SetEventHandle(event); @@ -2622,6 +2646,9 @@ void close_wasapi_stream(cubeb_stream * stm) stm->output_mixer.reset(); stm->input_mixer.reset(); stm->mix_buffer.clear(); + if (stm->linear_input_buffer) { + stm->linear_input_buffer->clear(); + } } void wasapi_stream_destroy(cubeb_stream * stm)