[player] Different timer catch up for files + remove timer abort

Timer abort should no longer apply since we may catch up for more
than a second. Introduce separate catch up strategies for files and
streams, since for files we can read at our own pace.
This commit is contained in:
ejurgensen 2016-02-28 22:28:37 +01:00
parent 220494e8b1
commit 3000341acd
1 changed files with 18 additions and 20 deletions

View File

@ -1608,7 +1608,6 @@ player_playback_cb(int fd, short what, void *arg)
{ {
struct timespec next_tick; struct timespec next_tick;
uint64_t overrun; uint64_t overrun;
uint32_t packet_send_count;
int ret; int ret;
// Check if we missed any timer expirations // Check if we missed any timer expirations
@ -1628,18 +1627,28 @@ player_playback_cb(int fd, short what, void *arg)
#endif /* __linux__ */ #endif /* __linux__ */
// The reason we get behind the playback timer may be that we are playing a // The reason we get behind the playback timer may be that we are playing a
// network stream. We might be consuming faster than the stream delivers, so // network stream OR that the source is slow to open OR some interruption.
// For streams, we might be consuming faster than the stream delivers, so
// when ffmpeg's buffer empties (might take a few hours) our av_read_frame() // when ffmpeg's buffer empties (might take a few hours) our av_read_frame()
// in transcode.c will begin to block, because ffmpeg has to wait for new data // in transcode.c will begin to block, because ffmpeg has to wait for new data
// from the stream server. In that situation we will skip reading data every // from the stream server.
// second tick until we have skipt PLAYER_TICKS_SKIP ticks. That should make //
// the source catch up. RTP destinations should be able to handle this // Our strategy to catch up with the timer depends on the source:
// gracefully if we just give them an rtptime that lets them know that some // - streams: We will skip reading data every second tick until we have
// packets were "lost". // skipt PLAYER_TICKS_SKIP ticks. That should make the source
// catch up. RTP destinations should be able to handle this
// gracefully if we just give them an rtptime that lets them know
// that some packets were "lost".
// - files: Just read and write like crazy until we have caught up.
if (overrun > PLAYER_TICKS_MAX_OVERRUN) if (overrun > PLAYER_TICKS_MAX_OVERRUN)
{ {
DPRINTF(E_WARN, L_PLAYER, "Behind the playback timer with %" PRIu64 " ticks, initiating catch up\n", overrun); DPRINTF(E_WARN, L_PLAYER, "Behind the playback timer with %" PRIu64 " ticks, initiating catch up\n", overrun);
ticks_skip = 2 * PLAYER_TICKS_SKIP + 1;
if (cur_streaming->data_kind == DATA_KIND_FILE)
ticks_skip = 0;
else
ticks_skip = 2 * PLAYER_TICKS_SKIP + 1;
} }
else if (ticks_skip > 0) else if (ticks_skip > 0)
ticks_skip--; ticks_skip--;
@ -1649,26 +1658,15 @@ player_playback_cb(int fd, short what, void *arg)
for (; overrun > 0; overrun--) for (; overrun > 0; overrun--)
next_tick = timespec_add(next_tick, tick_interval); next_tick = timespec_add(next_tick, tick_interval);
packet_send_count = 0;
do do
{ {
// Skip reading and writing every second tick if we are behind the source // Skip reading and writing every second tick if we are behind a nonfile source
if (ticks_skip % 2 == 0) if (ticks_skip % 2 == 0)
playback_write(); playback_write();
else else
last_rtptime += AIRTUNES_V2_PACKET_SAMPLES; last_rtptime += AIRTUNES_V2_PACKET_SAMPLES;
packet_timer_last = timespec_add(packet_timer_last, packet_time); packet_timer_last = timespec_add(packet_timer_last, packet_time);
packet_send_count++;
/* not possible to have more than 126 audio packets per second */
if (packet_send_count > 126)
{
DPRINTF(E_LOG, L_PLAYER, "Timing error detected during playback! Aborting.\n");
playback_abort();
return;
}
} }
while (timespec_cmp(packet_timer_last, next_tick) < 0); while (timespec_cmp(packet_timer_last, next_tick) < 0);