зеркало из https://github.com/mozilla/gecko-dev.git
Bug 776137 - Apply latency correction to audio stream position on macOS. r=padenot
--HG-- extra : rebase_source : ea7d68e32bdc1d3712b64a42f6fdaa75f0933988
This commit is contained in:
Родитель
4bfb789b0c
Коммит
f3e9b08714
|
@ -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 7401fc25a9d87ed57d49648883e3e5658305c1cb (2018-03-26 16:54:01 +0200)
|
||||
The git commit ID used was f34f392de5158feb46202e8ae58528bfb42f2759 (2018-03-27 17:45:10 -0400)
|
||||
|
|
|
@ -159,10 +159,12 @@ TEST(cubeb, duplex_collection_change)
|
|||
input_params.rate = 48000;
|
||||
input_params.channels = 1;
|
||||
input_params.layout = CUBEB_LAYOUT_MONO;
|
||||
input_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
output_params.format = STREAM_FORMAT;
|
||||
output_params.rate = 48000;
|
||||
output_params.channels = 2;
|
||||
output_params.layout = CUBEB_LAYOUT_STEREO;
|
||||
output_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
|
||||
r = cubeb_get_min_latency(ctx, &output_params, &latency_frames);
|
||||
ASSERT_EQ(r, CUBEB_OK) << "Could not get minimal latency";
|
||||
|
|
|
@ -348,6 +348,7 @@ void run_loopback_separate_streams_test(bool is_float)
|
|||
output_params.rate = SAMPLE_FREQUENCY;
|
||||
output_params.channels = 1;
|
||||
output_params.layout = CUBEB_LAYOUT_MONO;
|
||||
output_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
|
||||
std::unique_ptr<user_state_loopback> user_data(new user_state_loopback());
|
||||
ASSERT_TRUE(!!user_data) << "Error allocating user data";
|
||||
|
@ -515,6 +516,7 @@ void run_loopback_device_selection_test(bool is_float)
|
|||
output_params.rate = SAMPLE_FREQUENCY;
|
||||
output_params.channels = 1;
|
||||
output_params.layout = CUBEB_LAYOUT_MONO;
|
||||
output_params.prefs = CUBEB_STREAM_PREF_NONE;
|
||||
|
||||
std::unique_ptr<user_state_loopback> user_data(new user_state_loopback());
|
||||
ASSERT_TRUE(!!user_data) << "Error allocating user data";
|
||||
|
|
|
@ -70,6 +70,7 @@ static void audiounit_close_stream(cubeb_stream *stm);
|
|||
static int audiounit_setup_stream(cubeb_stream *stm);
|
||||
static vector<AudioObjectID>
|
||||
audiounit_get_devices_of_type(cubeb_device_type devtype);
|
||||
static UInt32 audiounit_get_device_presentation_latency(AudioObjectID devid, AudioObjectPropertyScope scope);
|
||||
|
||||
extern cubeb_ops const audiounit_ops;
|
||||
|
||||
|
@ -178,8 +179,7 @@ struct cubeb_stream {
|
|||
atomic<bool> draining{ false };
|
||||
/* Latency requested by the user. */
|
||||
uint32_t latency_frames = 0;
|
||||
atomic<uint64_t> current_latency_frames{ 0 };
|
||||
uint64_t hw_latency_frames = UINT64_MAX;
|
||||
atomic<uint32_t> current_latency_frames{ 0 };
|
||||
atomic<float> panning{ 0 };
|
||||
unique_ptr<cubeb_resampler, decltype(&cubeb_resampler_destroy)> resampler;
|
||||
/* This is true if a device change callback is currently running. */
|
||||
|
@ -320,19 +320,6 @@ AudioConvertHostTimeToNanos(uint64_t host_time)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int64_t
|
||||
audiotimestamp_to_latency(AudioTimeStamp const * tstamp, cubeb_stream * stream)
|
||||
{
|
||||
if (!(tstamp->mFlags & kAudioTimeStampHostTimeValid)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t pres = AudioConvertHostTimeToNanos(tstamp->mHostTime);
|
||||
uint64_t now = AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
|
||||
|
||||
return ((pres - now) * stream->output_desc.mSampleRate) / 1000000000LL;
|
||||
}
|
||||
|
||||
static void
|
||||
audiounit_set_global_latency(cubeb_stream * stm, uint32_t latency_frames)
|
||||
{
|
||||
|
@ -526,7 +513,6 @@ audiounit_output_callback(void * user_ptr,
|
|||
return noErr;
|
||||
}
|
||||
|
||||
stm->current_latency_frames = audiotimestamp_to_latency(tstamp, stm);
|
||||
if (stm->draining) {
|
||||
OSStatus r = AudioOutputUnitStop(stm->output_unit);
|
||||
assert(r == 0);
|
||||
|
@ -2541,6 +2527,14 @@ audiounit_setup_stream(cubeb_stream * stm)
|
|||
LOG("AudioUnitInitialize/output rv=%d", r);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
stm->current_latency_frames = audiounit_get_device_presentation_latency(stm->output_device.id, kAudioDevicePropertyScopeOutput);
|
||||
|
||||
Float64 unit_s;
|
||||
UInt32 size = sizeof(unit_s);
|
||||
if (AudioUnitGetProperty(stm->output_unit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &unit_s, &size) == noErr) {
|
||||
stm->current_latency_frames += static_cast<uint32_t>(unit_s * stm->output_desc.mSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
if (stm->input_unit && stm->output_unit) {
|
||||
|
@ -2764,7 +2758,11 @@ static int
|
|||
audiounit_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||
{
|
||||
assert(stm);
|
||||
*position = stm->frames_played;
|
||||
if (stm->current_latency_frames > stm->frames_played) {
|
||||
*position = 0;
|
||||
} else {
|
||||
*position = stm->frames_played - stm->current_latency_frames;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
|
@ -2775,74 +2773,7 @@ audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
//TODO
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
#else
|
||||
auto_lock lock(stm->mutex);
|
||||
if (stm->hw_latency_frames == UINT64_MAX) {
|
||||
UInt32 size;
|
||||
uint32_t device_latency_frames, device_safety_offset;
|
||||
double unit_latency_sec;
|
||||
AudioDeviceID output_device_id;
|
||||
OSStatus r;
|
||||
AudioObjectPropertyAddress latency_address = {
|
||||
kAudioDevicePropertyLatency,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
AudioObjectPropertyAddress safety_offset_address = {
|
||||
kAudioDevicePropertySafetyOffset,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
output_device_id = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_OUTPUT);
|
||||
if (output_device_id == kAudioObjectUnknown) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof(unit_latency_sec);
|
||||
r = AudioUnitGetProperty(stm->output_unit,
|
||||
kAudioUnitProperty_Latency,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
&unit_latency_sec,
|
||||
&size);
|
||||
if (r != noErr) {
|
||||
LOG("AudioUnitGetProperty/kAudioUnitProperty_Latency rv=%d", r);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof(device_latency_frames);
|
||||
r = AudioObjectGetPropertyData(output_device_id,
|
||||
&latency_address,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
&device_latency_frames);
|
||||
if (r != noErr) {
|
||||
LOG("AudioUnitGetPropertyData/latency_frames rv=%d", r);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof(device_safety_offset);
|
||||
r = AudioObjectGetPropertyData(output_device_id,
|
||||
&safety_offset_address,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
&device_safety_offset);
|
||||
if (r != noErr) {
|
||||
LOG("AudioUnitGetPropertyData/safety_offset rv=%d", r);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
/* This part is fixed and depend on the stream parameter and the hardware. */
|
||||
stm->hw_latency_frames =
|
||||
static_cast<uint32_t>(unit_latency_sec * stm->output_desc.mSampleRate)
|
||||
+ device_latency_frames
|
||||
+ device_safety_offset;
|
||||
}
|
||||
|
||||
*latency = stm->hw_latency_frames + stm->current_latency_frames;
|
||||
|
||||
*latency = stm->current_latency_frames;
|
||||
return CUBEB_OK;
|
||||
#endif
|
||||
}
|
||||
|
@ -3089,7 +3020,7 @@ static UInt32
|
|||
audiounit_get_device_presentation_latency(AudioObjectID devid, AudioObjectPropertyScope scope)
|
||||
{
|
||||
AudioObjectPropertyAddress adr = { 0, scope, kAudioObjectPropertyElementMaster };
|
||||
UInt32 size, dev, stream = 0, offset;
|
||||
UInt32 size, dev, stream = 0;
|
||||
AudioStreamID sid[1];
|
||||
|
||||
adr.mSelector = kAudioDevicePropertyLatency;
|
||||
|
@ -3106,13 +3037,7 @@ audiounit_get_device_presentation_latency(AudioObjectID devid, AudioObjectProper
|
|||
AudioObjectGetPropertyData(sid[0], &adr, 0, NULL, &size, &stream);
|
||||
}
|
||||
|
||||
adr.mSelector = kAudioDevicePropertySafetyOffset;
|
||||
size = sizeof(UInt32);
|
||||
if (AudioObjectGetPropertyData(devid, &adr, 0, NULL, &size, &offset) != noErr) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
return dev + stream + offset;
|
||||
return dev + stream;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Загрузка…
Ссылка в новой задаче