зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1136360 - Backout 3920b67e97a3 to fix A/V sync regressions (bug 1148299 & bug 1157886). r=backout
This commit is contained in:
Родитель
476a1225bf
Коммит
85e09e9b88
|
@ -216,8 +216,6 @@ struct cubeb_stream
|
||||||
|
|
||||||
/* Main handle on the WASAPI stream. */
|
/* Main handle on the WASAPI stream. */
|
||||||
IAudioClient * client;
|
IAudioClient * client;
|
||||||
/* Interface pointer to the clock, to estimate latency. */
|
|
||||||
IAudioClock * audio_clock;
|
|
||||||
/* Interface pointer to use the event-driven interface. */
|
/* Interface pointer to use the event-driven interface. */
|
||||||
IAudioRenderClient * render_client;
|
IAudioRenderClient * render_client;
|
||||||
/* Interface pointer to use the volume facilities. */
|
/* Interface pointer to use the volume facilities. */
|
||||||
|
@ -239,16 +237,8 @@ struct cubeb_stream
|
||||||
HANDLE refill_event;
|
HANDLE refill_event;
|
||||||
/* Each cubeb_stream has its own thread. */
|
/* Each cubeb_stream has its own thread. */
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
/* We synthesize our clock from the callbacks. This in fractional frames, in
|
/* We synthesize our clock from the callbacks. */
|
||||||
* the stream samplerate. */
|
LONG64 clock;
|
||||||
double clock;
|
|
||||||
UINT64 prev_position;
|
|
||||||
/* This is the clock value last time we reset the stream. This is in
|
|
||||||
* fractional frames, in the stream samplerate. */
|
|
||||||
double base_clock;
|
|
||||||
/* The latency in frames of the stream */
|
|
||||||
UINT32 latency_frames;
|
|
||||||
UINT64 device_frequency;
|
|
||||||
owned_critical_section * stream_reset_lock;
|
owned_critical_section * stream_reset_lock;
|
||||||
/* Maximum number of frames we can be requested in a callback. */
|
/* Maximum number of frames we can be requested in a callback. */
|
||||||
uint32_t buffer_frame_count;
|
uint32_t buffer_frame_count;
|
||||||
|
@ -353,28 +343,14 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void clock_add(cubeb_stream * stm, double value)
|
void clock_add(cubeb_stream * stm, LONG64 value)
|
||||||
{
|
{
|
||||||
auto_lock lock(stm->stream_reset_lock);
|
InterlockedExchangeAdd64(&stm->clock, value);
|
||||||
stm->clock += value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT64 clock_get(cubeb_stream * stm)
|
LONG64 clock_get(cubeb_stream * stm)
|
||||||
{
|
{
|
||||||
auto_lock lock(stm->stream_reset_lock);
|
return InterlockedExchangeAdd64(&stm->clock, 0);
|
||||||
return UINT64(stm->clock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void latency_set(cubeb_stream * stm, UINT32 value)
|
|
||||||
{
|
|
||||||
auto_lock lock(stm->stream_reset_lock);
|
|
||||||
stm->latency_frames = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 latency_get(cubeb_stream * stm)
|
|
||||||
{
|
|
||||||
auto_lock lock(stm->stream_reset_lock);
|
|
||||||
return stm->latency_frames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_upmix(cubeb_stream * stream)
|
bool should_upmix(cubeb_stream * stream)
|
||||||
|
@ -476,6 +452,8 @@ refill(cubeb_stream * stm, float * data, long frames_needed)
|
||||||
|
|
||||||
long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed);
|
long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed);
|
||||||
|
|
||||||
|
clock_add(stm, roundf(frames_needed * stream_to_mix_samplerate_ratio(stm)));
|
||||||
|
|
||||||
/* XXX: Handle this error. */
|
/* XXX: Handle this error. */
|
||||||
if (out_frames < 0) {
|
if (out_frames < 0) {
|
||||||
XASSERT(false);
|
XASSERT(false);
|
||||||
|
@ -547,10 +525,8 @@ wasapi_stream_render_loop(LPVOID stream)
|
||||||
/* We don't check if the drain is actually finished here, we just want to
|
/* We don't check if the drain is actually finished here, we just want to
|
||||||
* shutdown. */
|
* shutdown. */
|
||||||
if (stm->draining) {
|
if (stm->draining) {
|
||||||
LOG("DRAINED");
|
|
||||||
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case WAIT_OBJECT_0 + 1: { /* reconfigure */
|
case WAIT_OBJECT_0 + 1: { /* reconfigure */
|
||||||
|
@ -559,8 +535,6 @@ wasapi_stream_render_loop(LPVOID stream)
|
||||||
{
|
{
|
||||||
auto_lock lock(stm->stream_reset_lock);
|
auto_lock lock(stm->stream_reset_lock);
|
||||||
close_wasapi_stream(stm);
|
close_wasapi_stream(stm);
|
||||||
stm->base_clock = stm->clock;
|
|
||||||
stm->latency_frames = 0;
|
|
||||||
/* Reopen a stream and start it immediately. This will automatically pick the
|
/* Reopen a stream and start it immediately. This will automatically pick the
|
||||||
* new default device for this role. */
|
* new default device for this role. */
|
||||||
int r = setup_wasapi_stream(stm);
|
int r = setup_wasapi_stream(stm);
|
||||||
|
@ -588,16 +562,6 @@ wasapi_stream_render_loop(LPVOID stream)
|
||||||
|
|
||||||
long available = stm->buffer_frame_count - padding;
|
long available = stm->buffer_frame_count - padding;
|
||||||
|
|
||||||
clock_add(stm, available * stream_to_mix_samplerate_ratio(stm));
|
|
||||||
|
|
||||||
UINT64 position = 0;
|
|
||||||
HRESULT hr = stm->audio_clock->GetPosition(&position, NULL);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
double playing_frame = stm->mix_params.rate * (double)position / stm->device_frequency;
|
|
||||||
double last_written_frame = stm->clock - stm->base_clock;
|
|
||||||
latency_set(stm, std::max(last_written_frame - playing_frame, 0.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stm->draining) {
|
if (stm->draining) {
|
||||||
if (padding == 0) {
|
if (padding == 0) {
|
||||||
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
||||||
|
@ -1090,19 +1054,6 @@ int setup_wasapi_stream(cubeb_stream * stm)
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = stm->client->GetService(__uuidof(IAudioClock),
|
|
||||||
(void **)&stm->audio_clock);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
LOG("Could not get IAudioClock: %x.\n", hr);
|
|
||||||
return CUBEB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = stm->audio_clock->GetFrequency(&stm->device_frequency);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
LOG("Could not get the device frequency from IAudioClock: %x.\n", hr);
|
|
||||||
return CUBEB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = stm->client->GetService(__uuidof(IAudioRenderClient),
|
hr = stm->client->GetService(__uuidof(IAudioRenderClient),
|
||||||
(void **)&stm->render_client);
|
(void **)&stm->render_client);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -1161,14 +1112,11 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||||
stm->stream_params = stream_params;
|
stm->stream_params = stream_params;
|
||||||
stm->draining = false;
|
stm->draining = false;
|
||||||
stm->latency = latency;
|
stm->latency = latency;
|
||||||
stm->clock = 0.0;
|
stm->clock = 0;
|
||||||
stm->base_clock = 0.0;
|
|
||||||
stm->latency_frames = 0;
|
|
||||||
|
|
||||||
/* Null out WASAPI-specific state */
|
/* Null out WASAPI-specific state */
|
||||||
stm->resampler = NULL;
|
stm->resampler = NULL;
|
||||||
stm->client = NULL;
|
stm->client = NULL;
|
||||||
stm->audio_clock = NULL;
|
|
||||||
stm->render_client = NULL;
|
stm->render_client = NULL;
|
||||||
stm->audio_stream_volume = NULL;
|
stm->audio_stream_volume = NULL;
|
||||||
stm->device_enumerator = NULL;
|
stm->device_enumerator = NULL;
|
||||||
|
@ -1226,9 +1174,6 @@ void close_wasapi_stream(cubeb_stream * stm)
|
||||||
SafeRelease(stm->render_client);
|
SafeRelease(stm->render_client);
|
||||||
stm->render_client = NULL;
|
stm->render_client = NULL;
|
||||||
|
|
||||||
SafeRelease(stm->audio_clock);
|
|
||||||
stm->audio_clock = NULL;
|
|
||||||
|
|
||||||
SafeRelease(stm->audio_stream_volume);
|
SafeRelease(stm->audio_stream_volume);
|
||||||
stm->audio_stream_volume = NULL;
|
stm->audio_stream_volume = NULL;
|
||||||
|
|
||||||
|
@ -1338,20 +1283,7 @@ int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||||
{
|
{
|
||||||
XASSERT(stm && position);
|
XASSERT(stm && position);
|
||||||
|
|
||||||
UINT64 clock = clock_get(stm);
|
*position = clock_get(stm);
|
||||||
UINT32 latency = latency_get(stm);
|
|
||||||
|
|
||||||
*position = clock >= latency ? clock - latency : 0;
|
|
||||||
|
|
||||||
/* This can happen if the clock does not increase, for example, because the
|
|
||||||
* WASAPI endpoint buffer is full for now, and the latency naturally decreases
|
|
||||||
* because more samples have been played by the mixer process.
|
|
||||||
* We return the previous value to keep the clock monotonicaly increasing. */
|
|
||||||
if (*position < stm->prev_position) {
|
|
||||||
*position = stm->prev_position;
|
|
||||||
}
|
|
||||||
|
|
||||||
stm->prev_position = *position;
|
|
||||||
|
|
||||||
return CUBEB_OK;
|
return CUBEB_OK;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче