// get the next frame, when available. return 0 if underrun/stream reset. static short *buffer_get_frame(void) { short buf_fill; seq_t read; abuf_t *abuf = 0; unsigned short next; int i; pthread_mutex_lock(&ab_mutex); buf_fill = ab_write - ab_read; if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait if (ab_synced) fprintf(stderr, "\nunderrun.\n"); ab_buffering = 1; pthread_cond_wait(&ab_buffer_ready, &ab_mutex); ab_read++; buf_fill = ab_write - ab_read; bf_est_reset(buf_fill); pthread_mutex_unlock(&ab_mutex); return 0; } if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance fprintf(stderr, "\noverrun.\n"); ab_read = ab_write - buffer_start_fill; } read = ab_read; ab_read++; buf_fill = ab_write - ab_read; bf_est_update(buf_fill); // check if t+16, t+32, t+64, t+128, ... (START_FILL / 2) // packets have arrived... last-chance resend if (!ab_buffering) { for (i = 16; i < (START_FILL / 2); i = (i * 2)) { next = ab_read + i; abuf = audio_buffer + BUFIDX(next); if (!abuf->ready) { rtp_request_resend(next, next); } } } abuf_t *curframe = audio_buffer + BUFIDX(read); if (!curframe->ready) { fprintf(stderr, "\nmissing frame.\n"); memset(curframe->data, 0, FRAME_BYTES); } curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return curframe->data; }
// get the next frame, when available. return 0 if underrun/stream reset. static short *buffer_get_frame(void) { int16_t buf_fill; seq_t read, next; abuf_t *abuf = 0; int i; if (ab_buffering) return 0; pthread_mutex_lock(&ab_mutex); buf_fill = seq_diff(ab_read, ab_write); if (buf_fill < 1 || !ab_synced) { if (buf_fill < 1) warn("underrun %i (%04X:%04X)", buf_fill, ab_read, ab_write); ab_resync(); pthread_mutex_unlock(&ab_mutex); return 0; } if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance warn("overrun %i (%04X:%04X)", buf_fill, ab_read, ab_write); read = ab_read; ab_read = ab_write - config.buffer_start_fill; ab_reset((ab_write + 1 - BUFFER_FRAMES), ab_read); // reset any ready frames in those we've skipped (avoiding wrap around) } read = ab_read; ab_read++; buf_fill = seq_diff(ab_read, ab_write); bf_est_update(buf_fill); // check if t+16, t+32, t+64, t+128, ... resend focus boundary // packets have arrived... last-chance resend if (!ab_buffering) { for (i = 16; i <= resend_focus(config.buffer_start_fill); i = (i * 2)) { next = ab_read + i; abuf = audio_buffer + BUFIDX(next); if ((!abuf->ready) && (next < ab_write)){ rtp_request_resend(next, next); debug(1, "last chance resend T+%i, %04X (%04X:%04X)\n", i, next, ab_read, ab_write); } } } abuf_t *curframe = audio_buffer + BUFIDX(read); if (!curframe->ready) { debug(1, "missing frame %04X\n", read); memset(curframe->data, 0, FRAME_BYTES(frame_size)); } curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return curframe->data; }
// get the next frame, when available. return 0 if underrun/stream reset. static short *buffer_get_frame(void) { int16_t buf_fill; seq_t read, next; abuf_t *abuf = 0; int i; if (ab_buffering) return 0; pthread_mutex_lock(&ab_mutex); buf_fill = seq_diff(ab_read, ab_write); if (buf_fill < 1 || !ab_synced) { if (buf_fill < 1) warn("underrun."); ab_buffering = 1; pthread_mutex_unlock(&ab_mutex); return 0; } if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance warn("overrun."); ab_read = ab_write - config.buffer_start_fill; } read = ab_read; ab_read++; buf_fill = seq_diff(ab_read, ab_write); bf_est_update(buf_fill); // check if t+16, t+32, t+64, t+128, ... (buffer_start_fill / 2) // packets have arrived... last-chance resend if (!ab_buffering) { for (i = 16; i < (config.buffer_start_fill / 2); i = (i * 2)) { next = ab_read + i; abuf = audio_buffer + BUFIDX(next); if (!abuf->ready) { rtp_request_resend(next, next); } } } abuf_t *curframe = audio_buffer + BUFIDX(read); if (!curframe->ready) { debug(1, "missing frame %04X.", read); memset(curframe->data, 0, FRAME_BYTES(frame_size)); } curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return curframe->data; }
// get the next frame, when available. return 0 if underrun/stream reset. static short *buffer_get_frame(void) { short buf_fill; seq_t read; abuf_t *abuf = 0; pthread_mutex_lock(&ab_mutex); buf_fill = ab_write - ab_read; if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait if (ab_synced) fprintf(stderr, "\nunderrun.\n"); ab_buffering = 1; pthread_cond_wait(&ab_buffer_ready, &ab_mutex); ab_read++; buf_fill = ab_write - ab_read; bf_est_reset(buf_fill); pthread_mutex_unlock(&ab_mutex); return 0; } if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance fprintf(stderr, "\noverrun.\n"); ab_read = ab_write - buffer_start_fill; } read = ab_read; ab_read++; buf_fill = ab_write - ab_read; bf_est_update(buf_fill); if (!ab_buffering) { // check if the t+5th packet has arrived... last-chance resend read = ab_read + 5; abuf = audio_buffer + BUFIDX(read); if (!abuf->ready) { rtp_request_resend(read, read); abuf->ready = -1; } } abuf_t *curframe = audio_buffer + BUFIDX(read); if (!curframe->ready) { fprintf(stderr, "\nmissing frame.\n"); memset(curframe->data, 0, FRAME_BYTES); } curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return curframe->data; }
// get the next frame, when available. return 0 if underrun/stream reset. static inline short buffer_get_frame(signed short **inbuf) { unsigned short buf_fill; seq_t read; pthread_mutex_lock(&ab_mutex); buf_fill=BUF_FILL_SIZE(ab_write,ab_read); #ifdef DEBUG fprintf(stderr,"ab_write=%d ab_read=%d buf_fill=%d ab_buffering=%d\n",ab_write,ab_read,buf_fill,ab_buffering); #endif if (buf_fill < 1 || !ab_synced || ab_buffering) { // init or underrun. stop and wait #ifdef DEBUG if (ab_synced) fprintf(stderr, "\nunderrun.\n"); #endif ab_buffering = 1; pthread_cond_wait(&ab_buffer_ready, &ab_mutex); ab_read++; buf_fill=BUF_FILL_SIZE(ab_write,ab_read); bf_est_reset(buf_fill); pthread_mutex_unlock(&ab_mutex); return 0; } if (buf_fill < BUFFER_FRAMES) { #ifdef DEBUG fprintf(stderr, "pthread_cond_signal ab_buffer_full\n"); #endif pthread_cond_signal(&ab_buffer_full); } read = ab_read; ab_read++; buf_fill=BUF_FILL_SIZE(ab_write,ab_read); bf_est_update(buf_fill); abuf_t *curframe = audio_buffer + BUFIDX(read); if (curframe->ready) { alac_decode(*inbuf, curframe->data, curframe->len); curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return 1; } else { #ifdef DEBUG fprintf(stderr, "\nmissing frame.\n"); #endif curframe->ready = 0; pthread_mutex_unlock(&ab_mutex); return 0; } }
// get the next frame, when available. return 0 if underrun/stream reset. short *buffer_get_frame(void) { short buf_fill; seq_t read; pthread_mutex_lock(&ab_mutex); buf_fill = ab_write - ab_read; if (buf_fill < 1 || !ab_synced) { // init or underrun. stop and wait if (ab_synced) fprintf(stderr, "\nunderrun.\n"); ab_buffering = 1; pthread_cond_wait(&ab_buffer_ready, &ab_mutex); ab_read++; buf_fill = ab_write - ab_read; pthread_mutex_unlock(&ab_mutex); bf_est_reset(buf_fill); return 0; } if (buf_fill >= BUFFER_FRAMES) { // overrunning! uh-oh. restart at a sane distance fprintf(stderr, "\noverrun.\n"); ab_read = ab_write - START_FILL; } read = ab_read; ab_read++; pthread_mutex_unlock(&ab_mutex); buf_fill = ab_write - ab_read; bf_est_update(buf_fill); volatile abuf_t *curframe = audio_buffer + BUFIDX(read); if (!curframe->ready) { fprintf(stderr, "\nmissing frame.\n"); memset(curframe->data, 0, FRAME_BYTES); } curframe->ready = 0; return curframe->data; }