mirror of
https://github.com/owntone/owntone-server.git
synced 2025-11-09 13:39:47 -05:00
[player/outputs] Handle multiple quality levels + use rtp_common (WIP!)
* Untie Airtunes stuff further from player and non-Airplay outputs * Change raop.c to use rtp_common.c (step 1) * Change heartbeat of player to 100 ticks/sec, since we have untied from Airtunes 352 samples per packet (which equals 126 ticks/sec at 44100) Still a lot to be done in the player, since the rtptime's in it don't are probably broken.
This commit is contained in:
@@ -38,7 +38,10 @@
|
||||
#include "player.h"
|
||||
#include "outputs.h"
|
||||
|
||||
#define PACKET_SIZE STOB(AIRTUNES_V2_PACKET_SAMPLES)
|
||||
// Same as Airplay - maybe not optimal?
|
||||
#define ALSA_SAMPLES_PER_PACKET 352
|
||||
#define ALSA_PACKET_SIZE STOB(ALSA_SAMPLES_PER_PACKET, 16, 2)
|
||||
|
||||
// The maximum number of samples that the output is allowed to get behind (or
|
||||
// ahead) of the player position, before compensation is attempted
|
||||
#define ALSA_MAX_LATENCY 352
|
||||
@@ -573,15 +576,15 @@ playback_start(struct alsa_session *as, uint64_t pos, uint64_t start_pos)
|
||||
// buffering, because my sound card's start_threshold is not to be counted on.
|
||||
// Instead we allocate our own buffer, and when it is time to play we write as
|
||||
// much as we can to alsa's buffer.
|
||||
as->prebuf_len = (start_pos - pos) / AIRTUNES_V2_PACKET_SAMPLES + 1;
|
||||
if (as->prebuf_len > (3 * 44100 - offset) / AIRTUNES_V2_PACKET_SAMPLES)
|
||||
as->prebuf_len = (start_pos - pos) / ALSA_SAMPLES_PER_PACKET + 1;
|
||||
if (as->prebuf_len > (3 * 44100 - offset) / ALSA_SAMPLES_PER_PACKET)
|
||||
{
|
||||
DPRINTF(E_LOG, L_LAUDIO, "Sanity check of prebuf_len (%" PRIu32 " packets) failed\n", as->prebuf_len);
|
||||
return;
|
||||
}
|
||||
DPRINTF(E_DBG, L_LAUDIO, "Will prebuffer %d packets\n", as->prebuf_len);
|
||||
|
||||
as->prebuf = malloc(as->prebuf_len * PACKET_SIZE);
|
||||
as->prebuf = malloc(as->prebuf_len * ALSA_PACKET_SIZE);
|
||||
if (!as->prebuf)
|
||||
{
|
||||
DPRINTF(E_LOG, L_LAUDIO, "Out of memory for audio buffer (requested %" PRIu32 " packets)\n", as->prebuf_len);
|
||||
@@ -589,7 +592,7 @@ playback_start(struct alsa_session *as, uint64_t pos, uint64_t start_pos)
|
||||
}
|
||||
|
||||
as->pos = pos;
|
||||
as->start_pos = start_pos - AIRTUNES_V2_PACKET_SAMPLES;
|
||||
as->start_pos = start_pos - ALSA_SAMPLES_PER_PACKET;
|
||||
|
||||
// Dump PCM config data for E_DBG logging
|
||||
ret = snd_output_buffer_open(&output);
|
||||
@@ -620,32 +623,32 @@ buffer_write(struct alsa_session *as, uint8_t *buf, snd_pcm_sframes_t *avail, in
|
||||
snd_pcm_sframes_t nsamp;
|
||||
snd_pcm_sframes_t ret;
|
||||
|
||||
nsamp = AIRTUNES_V2_PACKET_SAMPLES;
|
||||
nsamp = ALSA_SAMPLES_PER_PACKET;
|
||||
|
||||
if (as->prebuf && (prebuffering || !prebuf_empty || *avail < AIRTUNES_V2_PACKET_SAMPLES))
|
||||
if (as->prebuf && (prebuffering || !prebuf_empty || *avail < ALSA_SAMPLES_PER_PACKET))
|
||||
{
|
||||
pkt = &as->prebuf[as->prebuf_head * PACKET_SIZE];
|
||||
pkt = &as->prebuf[as->prebuf_head * ALSA_PACKET_SIZE];
|
||||
|
||||
memcpy(pkt, buf, PACKET_SIZE);
|
||||
memcpy(pkt, buf, ALSA_PACKET_SIZE);
|
||||
|
||||
as->prebuf_head = (as->prebuf_head + 1) % as->prebuf_len;
|
||||
|
||||
if (prebuffering || *avail < AIRTUNES_V2_PACKET_SAMPLES)
|
||||
if (prebuffering || *avail < ALSA_SAMPLES_PER_PACKET)
|
||||
return 0; // No actual writing
|
||||
|
||||
// We will now set buf so that we will transfer as much as possible to ALSA
|
||||
buf = &as->prebuf[as->prebuf_tail * PACKET_SIZE];
|
||||
buf = &as->prebuf[as->prebuf_tail * ALSA_PACKET_SIZE];
|
||||
|
||||
if (as->prebuf_head > as->prebuf_tail)
|
||||
npackets = as->prebuf_head - as->prebuf_tail;
|
||||
else
|
||||
npackets = as->prebuf_len - as->prebuf_tail;
|
||||
|
||||
nsamp = npackets * AIRTUNES_V2_PACKET_SAMPLES;
|
||||
nsamp = npackets * ALSA_SAMPLES_PER_PACKET;
|
||||
while (nsamp > *avail)
|
||||
{
|
||||
npackets -= 1;
|
||||
nsamp -= AIRTUNES_V2_PACKET_SAMPLES;
|
||||
nsamp -= ALSA_SAMPLES_PER_PACKET;
|
||||
}
|
||||
|
||||
as->prebuf_tail = (as->prebuf_tail + npackets) % as->prebuf_len;
|
||||
@@ -685,7 +688,7 @@ sync_check(struct alsa_session *as, uint64_t rtptime, snd_pcm_sframes_t delay, i
|
||||
else
|
||||
npackets = 0;
|
||||
|
||||
pb_pos = rtptime - delay - AIRTUNES_V2_PACKET_SAMPLES * npackets;
|
||||
pb_pos = rtptime - delay - ALSA_SAMPLES_PER_PACKET * npackets;
|
||||
latency = cur_pos - (pb_pos - offset);
|
||||
|
||||
// If the latency is low or very different from our last measurement, we reset the sync_counter
|
||||
@@ -727,7 +730,7 @@ playback_write(struct alsa_session *as, uint8_t *buf, uint64_t rtptime)
|
||||
prebuffering = (as->pos < as->start_pos);
|
||||
prebuf_empty = (as->prebuf_head == as->prebuf_tail);
|
||||
|
||||
as->pos += AIRTUNES_V2_PACKET_SAMPLES;
|
||||
as->pos += ALSA_SAMPLES_PER_PACKET;
|
||||
|
||||
if (prebuffering)
|
||||
{
|
||||
@@ -771,7 +774,7 @@ playback_write(struct alsa_session *as, uint8_t *buf, uint64_t rtptime)
|
||||
}
|
||||
|
||||
// Fill the prebuf with audio before restarting, so we don't underrun again
|
||||
as->start_pos = as->pos + AIRTUNES_V2_PACKET_SAMPLES * (as->prebuf_len - 1);
|
||||
as->start_pos = as->pos + ALSA_SAMPLES_PER_PACKET * (as->prebuf_len - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -799,7 +802,7 @@ playback_pos_get(uint64_t *pos, uint64_t next_pkt)
|
||||
// Make pos the rtptime of the packet containing cur_pos
|
||||
*pos = next_pkt;
|
||||
while (*pos > cur_pos)
|
||||
*pos -= AIRTUNES_V2_PACKET_SAMPLES;
|
||||
*pos -= ALSA_SAMPLES_PER_PACKET;
|
||||
}
|
||||
|
||||
/* ------------------ INTERFACE FUNCTIONS CALLED BY OUTPUTS.C --------------- */
|
||||
|
||||
@@ -39,13 +39,13 @@
|
||||
#include "player.h"
|
||||
#include "outputs.h"
|
||||
|
||||
#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
|
||||
|
||||
#define FIFO_BUFFER_SIZE 65536 // pipe capacity on Linux >= 2.6.11
|
||||
#define FIFO_PACKET_SIZE 1408 // 352 samples/packet * 16 bit/sample * 2 channels
|
||||
|
||||
struct fifo_packet
|
||||
{
|
||||
/* pcm data */
|
||||
uint8_t samples[1408]; // STOB(AIRTUNES_V2_PACKET_SAMPLES)
|
||||
uint8_t samples[FIFO_PACKET_SIZE];
|
||||
|
||||
/* RTP-time of the first sample*/
|
||||
uint64_t rtptime;
|
||||
@@ -453,7 +453,7 @@ static void
|
||||
fifo_write(uint8_t *buf, uint64_t rtptime)
|
||||
{
|
||||
struct fifo_session *fifo_session = sessions;
|
||||
size_t length = STOB(AIRTUNES_V2_PACKET_SAMPLES);
|
||||
size_t length = FIFO_PACKET_SIZE;
|
||||
ssize_t bytes;
|
||||
struct fifo_packet *packet;
|
||||
uint64_t cur_pos;
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "outputs.h"
|
||||
#include "commands.h"
|
||||
|
||||
// From Airplay
|
||||
#define PULSE_SAMPLES_PER_PACKET 352
|
||||
#define PULSE_MAX_DEVICES 64
|
||||
#define PULSE_LOG_MAX 10
|
||||
|
||||
@@ -602,7 +604,7 @@ stream_open(struct pulse_session *ps, pa_stream_notify_cb_t cb)
|
||||
|
||||
flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
|
||||
|
||||
ps->attr.tlength = STOB(2 * ss.rate + AIRTUNES_V2_PACKET_SAMPLES - offset); // 2 second latency
|
||||
ps->attr.tlength = STOB(2 * ss.rate + PULSE_SAMPLES_PER_PACKET - offset, 16, 2); // 2 second latency
|
||||
ps->attr.maxlength = 2 * ps->attr.tlength;
|
||||
ps->attr.prebuf = (uint32_t)-1;
|
||||
ps->attr.minreq = (uint32_t)-1;
|
||||
@@ -760,7 +762,7 @@ pulse_write(uint8_t *buf, uint64_t rtptime)
|
||||
if (!sessions)
|
||||
return;
|
||||
|
||||
length = STOB(AIRTUNES_V2_PACKET_SAMPLES);
|
||||
length = STOB(PULSE_SAMPLES_PER_PACKET, 16, 2);
|
||||
|
||||
pa_threaded_mainloop_lock(pulse.mainloop);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user