diff --git a/src/raop_streamer.c b/src/raop_streamer.c index d09ffed7..8f06b4e1 100644 --- a/src/raop_streamer.c +++ b/src/raop_streamer.c @@ -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; setsockopt(ctx->http_listener, SOL_SOCKET, SO_SNDBUF, (void*) &i, sizeof(i)); rc &= ctx->http_listener > 0; rc &= listen(ctx->http_listener, 1) == 0; @@ -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 + 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 @@ -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 @@ -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 + 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; @@ -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; } @@ -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"); // is there a range request (chromecast non-compliance to HTTP !!!) if (ctx->range && ((str = kd_lookup(headers, "Range")) != NULL)) {