mirror of https://github.com/mpv-player/mpv
ao: add eof, pad_silence, and blocking arguments for ao_read_data
This commit is contained in:
parent
a791408659
commit
bfadd31957
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue