Bug 1732479 - Update libcubeb to 8ef5a1ff. r=cubeb-reviewers,padenot

Differential Revision: https://phabricator.services.mozilla.com/D128111
This commit is contained in:
Matthew Gregan 2021-10-12 19:25:57 +00:00
Родитель 9bca41ff8b
Коммит e7136be138
4 изменённых файлов: 86 добавлений и 25 удалений

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

@ -19,5 +19,5 @@ origin:
license: "ISC"
# update.sh will update this value
release: "f495dc982572a70701c5df930ef454b68bb6fe20 (2021-07-28 11:43:17 +1200)"
release: "ef5a1ffde99fe98ba0c28dab5128476e8aa384b8 (2021-10-12 08:09:34 +1300)"

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

@ -2178,13 +2178,13 @@ setup_wasapi_stream_one_side(cubeb_stream * stm,
return CUBEB_ERROR;
}
REFERENCE_TIME latency_hns;
REFERENCE_TIME latency_hns = frames_to_hns(stream_params->rate, stm->latency);
stm->input_bluetooth_handsfree = false;
uint32_t latency_frames = stm->latency;
cubeb_device_info device_info;
int rv = wasapi_create_device(stm->context, device_info,
stm->device_enumerator.get(), device.get());
if (rv == CUBEB_OK) {
if (wasapi_create_device(stm->context, device_info,
stm->device_enumerator.get(),
device.get()) == CUBEB_OK) {
const char * HANDSFREE_TAG = "BTHHFENUM";
size_t len = sizeof(HANDSFREE_TAG);
if (direction == eCapture) {
@ -2193,20 +2193,15 @@ setup_wasapi_stream_one_side(cubeb_stream * stm,
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;
uint32_t 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);
}
latency_hns = frames_to_hns(device_info.default_rate, latency_frames);
wasapi_destroy_device(&device_info);
} else {
stm->input_bluetooth_handsfree = false;
latency_hns = frames_to_hns(mix_params->rate, latency_frames);
LOG("Could not get cubeb_device_info.");
}

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

@ -121,6 +121,10 @@ struct cubeb_stream {
CRITICAL_SECTION lock;
uint64_t written;
float soft_volume;
/* For position wrap-around handling: */
size_t frame_size;
DWORD prev_pos_lo_dword;
DWORD pos_hi_dword;
};
static size_t
@ -557,6 +561,10 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream,
winmm_refill_stream(stm);
}
stm->frame_size = bytes_per_frame(stm->params);
stm->prev_pos_lo_dword = 0;
stm->pos_hi_dword = 0;
*stream = stm;
return CUBEB_OK;
@ -709,6 +717,58 @@ winmm_stream_stop(cubeb_stream * stm)
return CUBEB_OK;
}
/*
Microsoft wave audio docs say "samples are the preferred time format in which
to represent the current position", but relying on this causes problems on
Windows XP, the only OS cubeb_winmm is used on.
While the wdmaud.sys driver internally tracks a 64-bit position and ensures no
backward movement, the WinMM API limits the position returned from
waveOutGetPosition() to a 32-bit DWORD (this applies equally to XP x64). The
higher 32 bits are chopped off, and to an API consumer the position can appear
to move backward.
In theory, even a 32-bit TIME_SAMPLES position should provide plenty of
playback time for typical use cases before this pseudo wrap-around, e.g:
(2^32 - 1)/48000 = ~24:51:18 for 48.0 kHz stereo;
(2^32 - 1)/44100 = ~27:03:12 for 44.1 kHz stereo.
In reality, wdmaud.sys doesn't provide a TIME_SAMPLES position at all, only a
32-bit TIME_BYTES position, from which wdmaud.drv derives TIME_SAMPLES:
SamplePos = (BytePos * 8) / BitsPerFrame,
where BitsPerFrame = Channels * BitsPerSample,
Per dom\media\AudioSampleFormat.h, desktop builds always use 32-bit FLOAT32
samples, so the maximum for TIME_SAMPLES should be:
(2^29 - 1)/48000 = ~03:06:25;
(2^29 - 1)/44100 = ~03:22:54.
This might still be OK for typical browser usage, but there's also a bug in the
formula above: BytePos * 8 (BytePos << 3) is done on a 32-bit BytePos, without
first casting it to 64 bits, so the highest 3 bits, if set, would get shifted
out, and the maximum possible TIME_SAMPLES drops unacceptably low:
(2^26 - 1)/48000 = ~00:23:18;
(2^26 - 1)/44100 = ~00:25:22.
To work around these limitations, we just get the position in TIME_BYTES,
recover the 64-bit value, and do our own conversion to samples.
*/
/* Convert chopped 32-bit waveOutGetPosition() into 64-bit true position. */
static uint64_t
update_64bit_position(cubeb_stream * stm, DWORD pos_lo_dword)
{
/* Caller should be holding stm->lock. */
if (pos_lo_dword < stm->prev_pos_lo_dword) {
stm->pos_hi_dword++;
LOG("waveOutGetPosition() has wrapped around: %#lx -> %#lx",
stm->prev_pos_lo_dword, pos_lo_dword);
LOG("Wrap-around count = %#lx", stm->pos_hi_dword);
LOG("Current 64-bit position = %#llx",
(((uint64_t)stm->pos_hi_dword) << 32) | ((uint64_t)pos_lo_dword));
}
stm->prev_pos_lo_dword = pos_lo_dword;
return (((uint64_t)stm->pos_hi_dword) << 32) | ((uint64_t)pos_lo_dword);
}
static int
winmm_stream_get_position(cubeb_stream * stm, uint64_t * position)
{
@ -716,15 +776,17 @@ winmm_stream_get_position(cubeb_stream * stm, uint64_t * position)
MMTIME time;
EnterCriticalSection(&stm->lock);
time.wType = TIME_SAMPLES;
/* See the long comment above for why not just use TIME_SAMPLES here. */
time.wType = TIME_BYTES;
r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
LeaveCriticalSection(&stm->lock);
if (r != MMSYSERR_NOERROR || time.wType != TIME_SAMPLES) {
if (r != MMSYSERR_NOERROR || time.wType != TIME_BYTES) {
LeaveCriticalSection(&stm->lock);
return CUBEB_ERROR;
}
*position = time.u.sample;
*position = update_64bit_position(stm, time.u.cb) / stm->frame_size;
LeaveCriticalSection(&stm->lock);
return CUBEB_OK;
}
@ -734,20 +796,24 @@ winmm_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
{
MMRESULT r;
MMTIME time;
uint64_t written;
uint64_t written, position;
EnterCriticalSection(&stm->lock);
time.wType = TIME_SAMPLES;
/* See the long comment above for why not just use TIME_SAMPLES here. */
time.wType = TIME_BYTES;
r = waveOutGetPosition(stm->waveout, &time, sizeof(time));
written = stm->written;
LeaveCriticalSection(&stm->lock);
if (r != MMSYSERR_NOERROR || time.wType != TIME_SAMPLES) {
if (r != MMSYSERR_NOERROR || time.wType != TIME_BYTES) {
LeaveCriticalSection(&stm->lock);
return CUBEB_ERROR;
}
XASSERT(written - time.u.sample <= UINT32_MAX);
*latency = (uint32_t)(written - time.u.sample);
position = update_64bit_position(stm, time.u.cb);
written = stm->written;
LeaveCriticalSection(&stm->lock);
XASSERT((written - (position / stm->frame_size)) <= UINT32_MAX);
*latency = (uint32_t)(written - (position / stm->frame_size));
return CUBEB_OK;
}

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

@ -81,7 +81,7 @@ if [ -n "$rev" ]; then
echo "Updating moz.yaml failed."
exit 1
fi
rm moz.yaml.bak
rm -f moz.yaml.bak
[[ -n "$commits" ]] && echo -e "Pick commits:\n$commits"
else
echo "Remember to update moz.yaml with the version details."