Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions src/raop_streamer.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ raopst_resp_t raopst_init(struct in_addr host, struct in_addr peer, char *codec,
ctx->http_listener = bind_socket(ctx->host, &resp.hport, SOCK_STREAM);
} while (ctx->http_listener < 0 && port.count < port_range);

int i = 128*1024;
int i = 256*1024;

@philippe44 philippe44 May 4, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an observed issue or is this "just in case"? Because I think 128k is plenty for audio

setsockopt(ctx->http_listener, SOL_SOCKET, SO_SNDBUF, (void*) &i, sizeof(i));
rc &= ctx->http_listener > 0;
rc &= listen(ctx->http_listener, 1) == 0;
Expand Down Expand Up @@ -415,6 +415,11 @@ static void alac_decode(raopst_t *ctx, int16_t *dest, char *buf, int len, int *o

/*---------------------------------------------------------------------------*/
static void buffer_put_packet(raopst_t* ctx, seq_t seqno, unsigned rtptime, bool first, char* data, int len) {
// decode ALAC outside mutex to reduce contention with HTTP thread

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the point but I have to check that I'm not using that on some lower-end CPU where memory copy is not cheap

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you noticed that being an issue IRL?

int16_t decoded_buf[ctx->frame_size * 2];
int decoded_len = 0;
alac_decode(ctx, decoded_buf, data, len, &decoded_len);

pthread_mutex_lock(&ctx->ab_mutex);

/* if we have received a RECORD with a seqno, then this is the first allowed rtp sequence number
Expand Down Expand Up @@ -532,7 +537,8 @@ static void buffer_put_packet(raopst_t* ctx, seq_t seqno, unsigned rtptime, bool
}

if (abuf) {
alac_decode(ctx, abuf->data, data, len, &abuf->len);
memcpy(abuf->data, decoded_buf, decoded_len);
abuf->len = decoded_len;
abuf->ready = true;
abuf->missed = false;
// this is the local rtptime when this frame is expected to play
Expand Down Expand Up @@ -896,7 +902,13 @@ static short *_buffer_get_frame(raopst_t *ctx, size_t *bytes) {

if (!curframe->ready) {
LOG_DEBUG("[%p]: created zero frame at %d (W:%hu R:%hu)", ctx, now - playtime, ctx->ab_write, ctx->ab_read);
memset(curframe->data, 0, ctx->frame_size * 4);
// inject faint noise (~2 LSB) instead of pure silence to prevent FLAC decoder stalls

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never heard about "flac stalls" issue. Can you elaborate?

int16_t *samples = curframe->data;
static uint32_t noise_seed = 79;
for (int i = 0; i < ctx->frame_size * 2; i++) {
noise_seed = noise_seed * 1103515245 + 12345;
samples[i] = (int16_t)((noise_seed >> 16) & 0x03) - 1;
}
*bytes = ctx->frame_size * 4;
} else {
*bytes = curframe->len;
Expand Down Expand Up @@ -952,7 +964,9 @@ static void *http_thread_func(void *arg) {

if (sock != -1 && ctx->running) {
int on = 1;
int sndbuf = 256*1024;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on));
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*) &sndbuf, sizeof(sndbuf));
LOG_INFO("[%p]: got HTTP connection %u", ctx, sock);
} else continue;
}
Expand Down Expand Up @@ -1100,6 +1114,7 @@ static bool handle_http(raopst_t *ctx, int sock) {

kd_add(resp, "Server", "HairTunes");
kd_add(resp, "Content-Type", encoder_mimetype(ctx->encoder));
kd_add(resp, "TransferMode.dlna.org", "Streaming");

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are challenging my memory here ... I would have to re-read UPnP specs to see is this is correct. As you probably know, UPnP is a consistency disaster so I'm always worried to break something

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you can't do that here. This is a generic HTTP request that works for Chromecast and UPnP. You can't have UPnP headers.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a callback for that (sorry, but it just came back to me, I have not modified this code in a bit). So I'll do a modification in AirConnect


// is there a range request (chromecast non-compliance to HTTP !!!)
if (ctx->range && ((str = kd_lookup(headers, "Range")) != NULL)) {
Expand Down