Compute buffering and compensation without lock
Once underflow has been read with a lock, the buffering and compensation may be performed without shared variables.
This commit is contained in:
parent
0b8a5ca923
commit
eca8766545
1 changed files with 21 additions and 17 deletions
|
@ -180,6 +180,8 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
|
||||||
|
|
||||||
// Read with lock held, to be used after unlocking
|
// Read with lock held, to be used after unlocking
|
||||||
bool played = ap->played;
|
bool played = ap->played;
|
||||||
|
uint32_t underflow = ap->underflow;
|
||||||
|
|
||||||
if (played) {
|
if (played) {
|
||||||
uint32_t max_buffered_samples = ap->target_buffering
|
uint32_t max_buffered_samples = ap->target_buffering
|
||||||
+ 12 * SC_AUDIO_OUTPUT_BUFFER_MS * ap->sample_rate / 1000
|
+ 12 * SC_AUDIO_OUTPUT_BUFFER_MS * ap->sample_rate / 1000
|
||||||
|
@ -191,23 +193,8 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
|
||||||
" samples", skip_samples);
|
" samples", skip_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of samples added (or removed, if negative) for compensation
|
// reset (the current value was copied to a local variable)
|
||||||
int32_t instant_compensation =
|
ap->underflow = 0;
|
||||||
(int32_t) samples_written - frame->nb_samples;
|
|
||||||
int32_t inserted_silence = (int32_t) ap->underflow;
|
|
||||||
|
|
||||||
// The compensation must apply instantly, it must not be smoothed
|
|
||||||
ap->avg_buffering.avg += instant_compensation + inserted_silence;
|
|
||||||
|
|
||||||
ap->underflow = 0; // reset
|
|
||||||
|
|
||||||
// However, the buffering level must be smoothed
|
|
||||||
sc_average_push(&ap->avg_buffering, buffered_samples);
|
|
||||||
|
|
||||||
#ifndef SC_AUDIO_PLAYER_NDEBUG
|
|
||||||
LOGD("[Audio] buffered_samples=%" PRIu32 " avg_buffering=%f",
|
|
||||||
buffered_samples, sc_average_get(&ap->avg_buffering));
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
// SDL playback not started yet, do not accumulate more than
|
// SDL playback not started yet, do not accumulate more than
|
||||||
// max_initial_buffering samples, this would cause unnecessary delay
|
// max_initial_buffering samples, this would cause unnecessary delay
|
||||||
|
@ -230,6 +217,23 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
|
||||||
SDL_UnlockAudioDevice(ap->device);
|
SDL_UnlockAudioDevice(ap->device);
|
||||||
|
|
||||||
if (played) {
|
if (played) {
|
||||||
|
// Number of samples added (or removed, if negative) for compensation
|
||||||
|
int32_t instant_compensation =
|
||||||
|
(int32_t) samples_written - frame->nb_samples;
|
||||||
|
int32_t inserted_silence = (int32_t) underflow;
|
||||||
|
|
||||||
|
// The compensation must apply instantly, it must not be smoothed
|
||||||
|
ap->avg_buffering.avg += instant_compensation + inserted_silence;
|
||||||
|
|
||||||
|
|
||||||
|
// However, the buffering level must be smoothed
|
||||||
|
sc_average_push(&ap->avg_buffering, buffered_samples);
|
||||||
|
|
||||||
|
#ifndef SC_AUDIO_PLAYER_NDEBUG
|
||||||
|
LOGD("[Audio] buffered_samples=%" PRIu32 " avg_buffering=%f",
|
||||||
|
buffered_samples, sc_average_get(&ap->avg_buffering));
|
||||||
|
#endif
|
||||||
|
|
||||||
ap->samples_since_resync += samples_written;
|
ap->samples_since_resync += samples_written;
|
||||||
if (ap->samples_since_resync >= ap->sample_rate) {
|
if (ap->samples_since_resync >= ap->sample_rate) {
|
||||||
// Recompute compensation every second
|
// Recompute compensation every second
|
||||||
|
|
Loading…
Reference in a new issue