audio: introduce ao_read_data_nonblocking()

This behaves similar to ao_read_data() but does not block and may return
partial data.
This commit is contained in:
Thomas Weißschuh 2023-11-05 08:58:15 +01:00 committed by sfan5
parent a5c32ea52e
commit 4a134f441d
3 changed files with 41 additions and 11 deletions

View File

@ -170,21 +170,12 @@ static int read_buffer(struct ao *ao, void **data, int samples, bool *eof)
return pos;
}
// Read the given amount of samples in the user-provided data buffer. Returns
// the number of samples copied. If there is not enough data (buffer underrun
// or EOF), return the number of samples that could be copied, and fill the
// rest of the user-provided buffer with silence.
// This basically assumes that the audio device doesn't care about underruns.
// If this is called in paused mode, it will always return 0.
// The caller should set out_time_ns to the expected delay until the last sample
// reaches the speakers, in nanoseconds, using mp_time_ns() as reference.
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
static int ao_read_data_unlocked(struct ao *ao, void **data, int samples,
int64_t out_time_ns)
{
struct buffer_state *p = ao->buffer_state;
assert(!ao->driver->write);
mp_mutex_lock(&p->lock);
int pos = read_buffer(ao, data, samples, &(bool){0});
if (pos > 0)
@ -197,6 +188,41 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
mp_cond_broadcast(&p->wakeup);
}
return pos;
}
// Read the given amount of samples in the user-provided data buffer. Returns
// the number of samples copied. If there is not enough data (buffer underrun
// or EOF), return the number of samples that could be copied, and fill the
// rest of the user-provided buffer with silence.
// This basically assumes that the audio device doesn't care about underruns.
// If this is called in paused mode, it will always return 0.
// The caller should set out_time_ns to the expected delay until the last sample
// reaches the speakers, in nanoseconds, using mp_time_ns() as reference.
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
{
struct buffer_state *p = ao->buffer_state;
mp_mutex_lock(&p->lock);
int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns);
mp_mutex_unlock(&p->lock);
return pos;
}
// Like ao_read_data() but does not block and also may return partial data.
// Callers have to check the return value.
int ao_read_data_nonblocking(struct ao *ao, void **data, int samples, int64_t out_time_ns)
{
struct buffer_state *p = ao->buffer_state;
if (mp_mutex_trylock(&p->lock))
return 0;
int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns);
mp_mutex_unlock(&p->lock);
return pos;

View File

@ -200,6 +200,8 @@ struct ao_driver {
// These functions can be called by AOs.
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns);
MP_WARN_UNUSED_RESULT
int ao_read_data_nonblocking(struct ao *ao, void **data, int samples, int64_t out_time_ns);
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);

View File

@ -7,10 +7,12 @@
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format(printf, a1, a2)))
#define MP_NORETURN __attribute__((noreturn))
#define MP_FALLTHROUGH __attribute__((fallthrough))
#define MP_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#define MP_NORETURN
#define MP_FALLTHROUGH do {} while (0)
#define MP_WARN_UNUSED_RESULT
#endif
// Broken crap with __USE_MINGW_ANSI_STDIO