(first doubling) and ALSA's OSS emulation (second doubling) fed. The
initial buffer size is still under half a second, and feels close to
instant to this listener.
Also, the player thread now consumes packets immediately rather than
waiting for the next iteration, preventing a race where the (inner)
playing loop at the bottom of main() can terminate unnecessarily
early.
There's bits of debugging code left lying around commented out. It's
harmless for now!
/** @brief Output device */
/** @brief Output device */
-/** @brief Minimum low watermark
- *
- * We'll stop playing if there's only this many samples in the buffer. */
-unsigned minbuffer = 2 * 44100 / 10; /* 0.2 seconds */
+/** @brief Buffer low watermark in samples */
+unsigned minbuffer = 4 * (2 * 44100) / 10; /* 0.4 seconds */
-/** @brief Maximum buffer size
+/** @brief Maximum buffer size in samples
- * We'll stop reading from the network if we have this many samples. */
+ * We'll stop reading from the network if we have this many samples.
+ */
static unsigned maxbuffer;
/** @brief Received packets
static unsigned maxbuffer;
/** @brief Received packets
*/
void playrtp_fill_buffer(void) {
/* Discard current buffer contents */
*/
void playrtp_fill_buffer(void) {
/* Discard current buffer contents */
+ while(nsamples) {
+ //fprintf(stderr, "%8u/%u (%u) DROPPING\n", nsamples, maxbuffer, minbuffer);
info("Buffering...");
/* Wait until there's at least minbuffer samples available */
while(nsamples < minbuffer) {
info("Buffering...");
/* Wait until there's at least minbuffer samples available */
while(nsamples < minbuffer) {
+ //fprintf(stderr, "%8u/%u (%u) FILLING\n", nsamples, maxbuffer, minbuffer);
pthread_cond_wait(&cond, &lock);
}
/* Start from whatever is earliest */
pthread_cond_wait(&cond, &lock);
}
/* Start from whatever is earliest */
*bufptr++ = (int16_t)ntohs(*ptr++);
--i;
}
*bufptr++ = (int16_t)ntohs(*ptr++);
--i;
}
- /* We don't junk the packet here; a subsequent call to
- * playrtp_next_packet() will dispose of it (if it's actually done with). */
} else {
/* There is no suitable packet. We introduce 0s up to the next packet, or
* to fill the buffer if there's no next packet or that's too many. The
} else {
/* There is no suitable packet. We introduce 0s up to the next packet, or
* to fill the buffer if there's no next packet or that's too many. The
}
/* Advance timestamp */
next_timestamp += samples;
}
/* Advance timestamp */
next_timestamp += samples;
+ /* Junk obsolete packets */
+ playrtp_next_packet();
pthread_mutex_unlock(&lock);
return samples;
}
pthread_mutex_unlock(&lock);
return samples;
}
rcvbuf, target_rcvbuf);
} else
info("default socket receive buffer %d", rcvbuf);
rcvbuf, target_rcvbuf);
} else
info("default socket receive buffer %d", rcvbuf);
+ //info("minbuffer %u maxbuffer %u", minbuffer, maxbuffer);
if(logfp)
info("WARNING: -L option can impact performance");
if(control_socket) {
if(logfp)
info("WARNING: -L option can impact performance");
if(control_socket) {
while(nsamples >= minbuffer
|| (nsamples > 0
&& contains(pheap_first(&packets), next_timestamp))) {
while(nsamples >= minbuffer
|| (nsamples > 0
&& contains(pheap_first(&packets), next_timestamp))) {
+ //fprintf(stderr, "%8u/%u (%u) PLAYING\n", nsamples, maxbuffer, minbuffer);
pthread_cond_wait(&cond, &lock);
}
pthread_cond_wait(&cond, &lock);
}
+#if 0
+ if(nsamples) {
+ struct packet *p = pheap_first(&packets);
+ fprintf(stderr, "nsamples=%u (%u) next_timestamp=%"PRIx32", first packet is [%"PRIx32",%"PRIx32")\n",
+ nsamples, minbuffer, next_timestamp,p->timestamp,p->timestamp+p->nsamples);
+ }
+#endif
/* Stop playing for a bit until the buffer re-fills */
pthread_mutex_unlock(&lock);
backend->deactivate();
/* Stop playing for a bit until the buffer re-fills */
pthread_mutex_unlock(&lock);
backend->deactivate();