mirror of
https://github.com/mpv-player/mpv
synced 2024-12-25 00:02:13 +00:00
ao_jack: fix termination on the end of file
The player didn't quit when the end of a file was reached. The reason for this is that jack reported a constant audio delay even when all audio was done playing. Whether that was recognized as EOF by the player depended whether the exact value was higher or lower than the player's threshhold for what it considers no more audio. get_delay() should return amount of time it takes until the last sample written to the audio buffer reaches the speaker. Therefore, we have to track the estimated time when the last sample is done, and subtract it from the calculated latency. Basically, the latency is the only amount of time left in the delay, and it should go towards 0 as audio reaches ths speakers. I'm not sure if this is correct, but at least it solves the problem. One suspicious thing is that we use system time to estimate the end of the audio time. Maybe using jack_frame_time() would be more correct. But apart from this, there doesn't seem to be a better way to handle this.
This commit is contained in:
parent
5b3fd09908
commit
d268d896d9
@ -60,10 +60,12 @@ struct priv {
|
||||
int connect;
|
||||
int autostart;
|
||||
int stdlayout;
|
||||
int last_chunk;
|
||||
volatile int paused;
|
||||
volatile int underrun;
|
||||
volatile float callback_interval;
|
||||
volatile float callback_time;
|
||||
volatile float last_ok_time; // last time real audio was played
|
||||
|
||||
int num_ports;
|
||||
struct port_ring ports[MP_NUM_CHANNELS];
|
||||
@ -128,11 +130,15 @@ process(jack_nframes_t nframes, void *arg)
|
||||
underrun = 1;
|
||||
}
|
||||
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
|
||||
if (underrun)
|
||||
p->underrun = 1;
|
||||
|
||||
if (!p->underrun)
|
||||
p->last_ok_time = now;
|
||||
|
||||
if (p->estimate) {
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
float diff = p->callback_time + p->callback_interval - now;
|
||||
if ((diff > -0.002) && (diff < 0.002))
|
||||
p->callback_time += p->callback_interval;
|
||||
@ -289,14 +295,23 @@ static float get_delay(struct ao *ao)
|
||||
struct priv *p = ao->priv;
|
||||
int buffered = mp_ring_buffered(p->ports[0].ring); // could be less
|
||||
float in_jack = p->jack_latency;
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
|
||||
if (p->estimate && p->callback_interval > 0) {
|
||||
float elapsed = mp_time_us() / 1000000.0 - p->callback_time;
|
||||
in_jack += p->callback_interval - elapsed;
|
||||
if (in_jack < 0)
|
||||
in_jack = 0;
|
||||
}
|
||||
|
||||
if (p->underrun && !buffered && p->last_chunk) {
|
||||
// Report correct buffer drainage, when our buffer is empty, but jack
|
||||
// and/or the audio device still have some audio to play.
|
||||
// Assumes audio clock goes at about the same speed as the system time.
|
||||
in_jack += p->last_ok_time - now;
|
||||
}
|
||||
|
||||
if (in_jack < 0)
|
||||
in_jack = 0;
|
||||
|
||||
return (float)buffered / (float)ao->bps + in_jack;
|
||||
}
|
||||
|
||||
@ -369,6 +384,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
|
||||
}
|
||||
|
||||
p->underrun = 0;
|
||||
p->last_chunk = flags & AOPLAY_FINAL_CHUNK;
|
||||
return ret / ao->sstride;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user