ao: add eof, pad_silence, and blocking arguments for ao_read_data

This commit is contained in:
Misaki Kasumi 2024-04-22 19:47:34 +08:00 committed by sfan5
parent a791408659
commit bfadd31957
11 changed files with 26 additions and 34 deletions

View File

@ -564,7 +564,7 @@ static MP_THREAD_VOID ao_thread(void *arg)
int64_t ts = mp_time_ns();
ts += MP_TIME_S_TO_NS(read_samples / (double)(ao->samplerate));
ts += MP_TIME_S_TO_NS(AudioTrack_getLatency(ao));
int samples = ao_read_data_nonblocking(ao, &p->chunk, read_samples, ts);
int samples = ao_read_data(ao, &p->chunk, read_samples, ts, NULL, false, false);
int ret = AudioTrack_write(ao, samples * ao->sstride);
if (ret >= 0) {
p->written_frames += ret / ao->sstride;

View File

@ -97,7 +97,7 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
int64_t end = mp_time_ns();
end += MP_TIME_S_TO_NS(p->device_latency);
end += ca_get_latency(ts) + ca_frames_to_ns(ao, frames);
ao_read_data(ao, planes, frames, end);
ao_read_data(ao, planes, frames, end, NULL, true, true);
return noErr;
}

View File

@ -76,7 +76,7 @@ static void feed(struct ao *ao)
int64_t cur_time_mp = mp_time_ns();
int64_t end_time_av = MPMAX(p->end_time_av, cur_time_av);
int64_t time_delta = CMTimeGetNanoseconds(CMTimeMake(request_sample_count, samplerate));
int real_sample_count = ao_read_data_nonblocking(ao, data, request_sample_count, end_time_av - cur_time_av + cur_time_mp + time_delta);
int real_sample_count = ao_read_data(ao, data, request_sample_count, end_time_av - cur_time_av + cur_time_mp + time_delta, NULL, false, false);
if (real_sample_count == 0) {
// avoid spinning by blocking the thread
mp_sleep_ns(10000000);

View File

@ -91,7 +91,7 @@ static OSStatus render_cb_lpcm(void *ctx, AudioUnitRenderActionFlags *aflags,
int64_t end = mp_time_ns();
end += p->hw_latency_ns + ca_get_latency(ts) + ca_frames_to_ns(ao, frames);
// don't use the returned sample count since CoreAudio always expects full frames
ao_read_data(ao, planes, frames, end);
ao_read_data(ao, planes, frames, end, NULL, true, true);
return noErr;
}

View File

@ -181,7 +181,7 @@ static OSStatus render_cb_compressed(
end += p->hw_latency_ns + ca_get_latency(ts)
+ ca_frames_to_ns(ao, pseudo_frames);
ao_read_data(ao, &buf.mData, pseudo_frames, end);
ao_read_data(ao, &buf.mData, pseudo_frames, end, NULL, true, true);
if (p->spdif_hack)
bad_hack_mygodwhy(buf.mData, pseudo_frames * ao->channels.num);

View File

@ -124,7 +124,7 @@ static int process(jack_nframes_t nframes, void *arg)
int64_t end_time = mp_time_ns();
end_time += MP_TIME_S_TO_NS((jack_latency + nframes) / (double)ao->samplerate);
ao_read_data(ao, buffers, nframes, end_time);
ao_read_data(ao, buffers, nframes, end_time, NULL, true, true);
return 0;
}

View File

@ -81,7 +81,7 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
delay = p->frames_per_enqueue / (double)ao->samplerate;
delay += p->audio_latency;
ao_read_data(ao, &p->buf, p->frames_per_enqueue,
mp_time_ns() + MP_TIME_S_TO_NS(delay));
mp_time_ns() + MP_TIME_S_TO_NS(delay), NULL, true, true);
res = (*buffer_queue)->Enqueue(buffer_queue, p->buf, p->bytes_per_enqueue);
if (res != SL_RESULT_SUCCESS)

View File

@ -206,7 +206,7 @@ static void on_process(void *userdata)
#endif
end_time -= pw_stream_get_nsec(p->stream) - time.now;
int samples = ao_read_data_nonblocking(ao, data, nframes, end_time);
int samples = ao_read_data(ao, data, nframes, end_time, NULL, false, false);
b->size = samples;
for (int i = 0; i < buf->n_datas; i++) {

View File

@ -61,7 +61,7 @@ static void audio_callback(void *userdata, Uint8 *stream, int len)
// fixed latency.
double delay = 2 * len / (double)ao->bps;
ao_read_data(ao, data, len / ao->sstride, mp_time_ns() + MP_TIME_S_TO_NS(delay));
ao_read_data(ao, data, len / ao->sstride, mp_time_ns() + MP_TIME_S_TO_NS(delay), NULL, true, true);
}
static void uninit(struct ao *ao)

View File

@ -178,12 +178,12 @@ static int read_buffer(struct ao *ao, void **data, int samples, bool *eof,
}
static int ao_read_data_locked(struct ao *ao, void **data, int samples,
int64_t out_time_ns, bool pad_silence)
int64_t out_time_ns, bool *eof, bool pad_silence)
{
struct buffer_state *p = ao->buffer_state;
assert(!ao->driver->write);
int pos = read_buffer(ao, data, samples, &(bool){0}, pad_silence);
int pos = read_buffer(ao, data, samples, eof, pad_silence);
if (pos > 0)
p->end_time_ns = out_time_ns;
@ -206,29 +206,23 @@ static int ao_read_data_locked(struct ao *ao, void **data, int samples,
// 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)
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns, bool *eof, bool pad_silence, bool blocking)
{
struct buffer_state *p = ao->buffer_state;
mp_mutex_lock(&p->lock);
if (blocking) {
mp_mutex_lock(&p->lock);
} else if (mp_mutex_trylock(&p->lock)) {
return 0;
}
int pos = ao_read_data_locked(ao, data, samples, out_time_ns, true);
bool eof_buf;
if (eof == NULL) {
// This is a public API. We want to reduce the cognitive burden of the caller.
eof = &eof_buf;
}
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_locked(ao, data, samples, out_time_ns, false);
int pos = ao_read_data_locked(ao, data, samples, out_time_ns, eof, pad_silence);
mp_mutex_unlock(&p->lock);
@ -244,7 +238,7 @@ int ao_read_data_converted(struct ao *ao, struct ao_convert_fmt *fmt,
void *ndata[MP_NUM_CHANNELS] = {0};
if (!ao_need_conversion(fmt))
return ao_read_data(ao, data, samples, out_time_ns);
return ao_read_data(ao, data, samples, out_time_ns, NULL, true, true);
assert(ao->format == fmt->src_fmt);
assert(ao->channels.num == fmt->channels);
@ -264,7 +258,7 @@ int ao_read_data_converted(struct ao *ao, struct ao_convert_fmt *fmt,
for (int n = 0; n < planes; n++)
ndata[n] = p->convert_buffer + n * src_plane_size;
int res = ao_read_data(ao, ndata, samples, out_time_ns);
int res = ao_read_data(ao, ndata, samples, out_time_ns, NULL, true, true);
ao_convert_inplace(fmt, ndata, samples);
for (int n = 0; n < planes; n++)

View File

@ -201,9 +201,7 @@ 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);
int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns, bool *eof, bool pad_silence, bool blocking);
bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s,
struct mp_chmap *map);