Bug 1902263 - update libcubeb to revision bbbe5bb. r=cubeb-reviewers,padenot

Differential Revision: https://phabricator.services.mozilla.com/D216196
This commit is contained in:
John Lin 2024-07-10 19:01:28 +00:00
Родитель 848b37f67d
Коммит c2c97f3f71
2 изменённых файлов: 47 добавлений и 18 удалений

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

@ -9,8 +9,8 @@ origin:
description: "Cross platform audio library"
url: https://github.com/mozilla/cubeb
license: ISC
release: 063a090221250a5e7c6c61a3f94c95f60cfda722 (2024-07-08T16:08:38Z).
revision: 063a090221250a5e7c6c61a3f94c95f60cfda722
release: bbbe5bb0b29ed64cc7dd191d7a72fe24bba0d284 (2024-07-10T09:10:17Z).
revision: bbbe5bb0b29ed64cc7dd191d7a72fe24bba0d284
vendoring:
url: https://github.com/mozilla/cubeb

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

@ -140,10 +140,14 @@ struct AAudioTimingInfo {
/* To guess the current position of the stream when it's playing, the elapsed
* time between the last callback and now is used. However, when the stream was
* stopped and there was no new callback after playing restarted yet, the time
* spent in stopped state should be excluded.
* spent in stopped state should be excluded. It's also necessary to track the
* number of audio frames written to stream before reinitialization so it can be
* used to offset the position later, because
* `AAudioTimingInfo.output_frame_index` will restart from zero after
* reinitializing.
* This class defines an internal state machine that takes the stream state
* changes and callback emissions as events to changes it own statesm and
* calculates played time accordingly.
* changes and callback emissions as events to changes it own states and
* estimates played time accordingly.
*
* A simplified |stream_state| transitions of playing looks like:
* INIT -> [STARTING/STARTED -> callback* -> STOPPING/STOPPED]* -> SHUTDOWN|INIT
@ -162,7 +166,7 @@ struct AAudioTimingInfo {
* - Resume -(STARTING)-> Resume
* - Pause -(INIT)-> None
*/
class position_interpolator {
class position_estimate {
public:
// Called with the current time when stopping the stream.
void stop(uint64_t timestamp)
@ -188,7 +192,8 @@ public:
}
// Calculate how much time the stream bas been playing since last callback.
uint64_t compute(uint64_t now, uint64_t last_callback_timestamp)
uint64_t elapsed_time_since_callback(uint64_t now,
uint64_t last_callback_timestamp)
{
if (in_state<Play>()) {
if (callback_timestamp != last_callback_timestamp) {
@ -215,6 +220,18 @@ public:
}
}
// Called when reinitializing stream. The input parameter is how many frames
// have already been written to AAudio since the first initialization.
void reinit(uint64_t position)
{
init_position = position;
state = None{};
callback_timestamp = 0;
}
// Frame index when last reinitialized.
uint64_t initial_position() { return init_position; }
private:
template <typename T> void set_state() { state.emplace<T>(); }
@ -255,8 +272,10 @@ private:
uint64_t pause_time; // Elapsed time from stopping to starting stream.
};
std::variant<None, Play, Pause, Resume> state;
// Keep track input callback timestamp to detect callback emission.
// Track input callback timestamp to detect callback emission.
uint64_t callback_timestamp{0};
// Track number of written frames to adjust position after reinitialization.
uint64_t init_position{0};
};
struct cubeb_stream {
@ -297,7 +316,7 @@ struct cubeb_stream {
bool voice_input{};
bool voice_output{};
uint64_t previous_clock{};
position_interpolator interpolator;
position_estimate pos_estimate;
};
struct cubeb {
@ -1021,12 +1040,18 @@ reinitialize_stream(cubeb_stream * stm)
state == stream_state::STARTING ||
state == stream_state::DRAINING;
int err = aaudio_stream_stop_locked(stm, lock);
// get total number of written frames before destroying the stream.
uint64_t total_frames = stm->pos_estimate.initial_position() +
WRAP(AAudioStream_getFramesWritten)(stm->ostream);
// error ignored.
aaudio_stream_destroy_locked(stm, lock);
err = aaudio_stream_init_impl(stm, lock);
assert(stm->in_use.load());
// set the new initial position.
stm->pos_estimate.reinit(total_frames);
if (err != CUBEB_OK) {
aaudio_stream_destroy_locked(stm, lock);
LOG("aaudio_stream_init_impl error while reiniting: %s",
@ -1174,7 +1199,8 @@ aaudio_stream_destroy_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
}
stm->timing_info.invalidate();
stm->interpolator = {};
stm->previous_clock = 0;
stm->pos_estimate = {};
if (stm->resampler) {
cubeb_resampler_destroy(stm->resampler);
@ -1545,7 +1571,7 @@ aaudio_stream_start_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
}
if (success) {
stm->interpolator.start(now_ns());
stm->pos_estimate.start(now_ns());
stm->context->state.waiting.store(true);
stm->context->state.cond.notify_one();
}
@ -1654,7 +1680,7 @@ aaudio_stream_stop_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
}
if (success) {
stm->interpolator.stop(now_ns());
stm->pos_estimate.stop(now_ns());
stm->context->state.waiting.store(true);
stm->context->state.cond.notify_one();
}
@ -1669,6 +1695,7 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position)
lock_guard lock(stm->mutex);
stream_state state = stm->state.load();
uint64_t init_position = stm->pos_estimate.initial_position();
AAudioStream * stream = stm->ostream ? stm->ostream : stm->istream;
switch (state) {
case stream_state::ERROR:
@ -1679,7 +1706,7 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position)
case stream_state::STOPPING:
// getTimestamp is only valid when the stream is playing.
// Simply return the number of frames passed to aaudio
*position = WRAP(AAudioStream_getFramesRead)(stream);
*position = init_position + WRAP(AAudioStream_getFramesRead)(stream);
if (*position < stm->previous_clock) {
*position = stm->previous_clock;
} else {
@ -1697,7 +1724,7 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position)
// No callback yet, the stream hasn't really started.
if (stm->previous_clock == 0 && !stm->timing_info.updated()) {
LOG("Not timing info yet");
*position = 0;
*position = init_position;
return CUBEB_OK;
}
@ -1705,10 +1732,12 @@ aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position)
LOGV("AAudioTimingInfo idx:%lu tstamp:%lu latency:%u",
info.output_frame_index, info.tstamp, info.output_latency);
// Interpolate client side since the last callback.
uint64_t interpolation = stm->sample_rate *
stm->interpolator.compute(now_ns(), info.tstamp) /
NS_PER_S;
*position = info.output_frame_index + interpolation - info.output_latency;
uint64_t interpolation =
(stm->sample_rate *
stm->pos_estimate.elapsed_time_since_callback(now_ns(), info.tstamp) /
NS_PER_S);
*position = init_position + info.output_frame_index + interpolation -
info.output_latency;
if (*position < stm->previous_clock) {
*position = stm->previous_clock;
} else {