void player_put_packet(seq_t seqno, uint8_t *data, int len) { abuf_t *abuf = 0; int16_t buf_fill; pthread_mutex_lock(&ab_mutex); if (!ab_synced) { debug(1, "syncing to first seqno %04X\n", seqno); ab_write = seqno-1; ab_read = seqno; ab_synced = 1; } if (seq_diff(ab_write, seqno) == 1) { // expected packet abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } else if (seq_order(ab_write, seqno)) { // newer than expected // Be careful with new packets that are in advance // Those more than a buffer size in advance will cause an Overrun // When buffering the valid threshold should be the buffer fill target itself which should re-sync if (ab_buffering && (seq_diff(ab_read, seqno) > config.buffer_start_fill)) { warn("out of range re-sync %04X (%04X:%04X)", seqno, ab_read, ab_write); ab_resync(); ab_synced = 1; ab_read = seqno; ab_write = seqno; abuf = audio_buffer + BUFIDX(seqno); } else { debug(1, "advance packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); rtp_request_resend(ab_write+1, seqno-1); abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } } else if (seq_order(ab_read, seqno)) { // late but not yet played abuf = audio_buffer + BUFIDX(seqno); if (abuf->ready) { // discard this frame if frame previously received abuf =0; debug(1, "duplicate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); } } else { // too late. debug(1, "late packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); } buf_fill = seq_diff(ab_read, ab_write); pthread_mutex_unlock(&ab_mutex); if (abuf) { alac_decode(abuf->data, data, len); abuf->ready = 1; } pthread_mutex_lock(&ab_mutex); if (ab_buffering && buf_fill >= config.buffer_start_fill) { debug(1, "buffering over. starting play (%04X:%04X)\n", ab_read, ab_write); ab_buffering = 0; } pthread_mutex_unlock(&ab_mutex); }
// 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; }
void buffer_put_packet(seq_t seqno, char *data, int len) { volatile abuf_t *abuf = 0; short read; short buf_fill; pthread_mutex_lock(&ab_mutex); if (!ab_synced) { ab_write = seqno; ab_read = seqno-1; ab_synced = 1; } if (seqno == ab_write+1) { // expected packet abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } else if (seq_order(ab_write, seqno)) { // newer than expected rtp_request_resend(ab_write, seqno-1); abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } else if (seq_order(ab_read, seqno)) { // late but not yet played abuf = audio_buffer + BUFIDX(seqno); } else { // too late. fprintf(stderr, "\nlate packet %04X (%04X:%04X)\n", seqno, ab_read, ab_write); } buf_fill = ab_write - ab_read; pthread_mutex_unlock(&ab_mutex); if (abuf) { alac_decode(abuf->data, data, len); abuf->ready = 1; } if (ab_buffering && buf_fill >= buffer_start_fill) { ab_buffering = 0; pthread_cond_signal(&ab_buffer_ready); } if (!ab_buffering) { // check if the t+10th packet has arrived... last-chance resend read = ab_read + 10; abuf = audio_buffer + BUFIDX(read); if (abuf->ready != 1) { rtp_request_resend(read, read); abuf->ready = -1; } } }
// reset the audio frames in the range to NOT ready static void ab_reset(seq_t from, seq_t to) { abuf_t *abuf = 0; while (seq_diff(from, to)) { abuf = audio_buffer + BUFIDX(from); abuf->ready = 0; from++; } }
void player_put_packet(seq_t seqno, uint8_t *data, int len) { abuf_t *abuf = 0; int16_t buf_fill; pthread_mutex_lock(&ab_mutex); if (!ab_synced) { debug(2, "syncing to first seqno %04X\n", seqno); ab_write = seqno-1; ab_read = seqno; ab_synced = 1; } if (seq_diff(ab_write, seqno) == 1) { // expected packet abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } else if (seq_order(ab_write, seqno)) { // newer than expected rtp_request_resend(ab_write+1, seqno-1); abuf = audio_buffer + BUFIDX(seqno); ab_write = seqno; } else if (seq_order(ab_read, seqno)) { // late but not yet played abuf = audio_buffer + BUFIDX(seqno); } else { // too late. debug(1, "late packet %04X (%04X:%04X)", seqno, ab_read, ab_write); } buf_fill = seq_diff(ab_read, ab_write); pthread_mutex_unlock(&ab_mutex); if (abuf) { alac_decode(abuf->data, data, len); abuf->ready = 1; } pthread_mutex_lock(&ab_mutex); if (ab_buffering && buf_fill >= config.buffer_start_fill) { debug(1, "buffering over. starting play\n"); ab_buffering = 0; bf_est_reset(buf_fill); } pthread_mutex_unlock(&ab_mutex); }
// 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; }
// get the next frame, when available. return 0 if underrun/stream reset. static abuf_t *buffer_get_frame(void) { int16_t buf_fill; uint64_t local_time_now; // struct timespec tn; abuf_t *abuf = 0; int i; abuf_t *curframe; pthread_mutex_lock(&ab_mutex); int wait; int32_t dac_delay = 0; do { // get the time local_time_now = get_absolute_time_in_fp(); // if config.timeout (default 120) seconds have elapsed since the last audio packet was // received, then we should stop. // config.timeout of zero means don't check..., but iTunes may be confused by a long gap // followed by a resumption... if ((time_of_last_audio_packet != 0) && (shutdown_requested == 0) && (config.dont_check_timeout == 0)) { uint64_t ct = config.timeout; // go from int to 64-bit int if ((local_time_now > time_of_last_audio_packet) && (local_time_now - time_of_last_audio_packet >= ct << 32)) { debug(1, "As Yeats almost said, \"Too long a silence / can make a stone of the heart\""); rtsp_request_shutdown_stream(); shutdown_requested = 1; } } int rco = get_requested_connection_state_to_output(); if (connection_state_to_output != rco) { connection_state_to_output = rco; // change happening if (connection_state_to_output == 0) { // going off pthread_mutex_lock(&flush_mutex); flush_requested = 1; pthread_mutex_unlock(&flush_mutex); } } pthread_mutex_lock(&flush_mutex); if (flush_requested == 1) { if (config.output->flush) config.output->flush(); ab_resync(); first_packet_timestamp = 0; first_packet_time_to_play = 0; time_since_play_started = 0; flush_requested = 0; } pthread_mutex_unlock(&flush_mutex); uint32_t flush_limit = 0; if (ab_synced) { do { curframe = audio_buffer + BUFIDX(ab_read); if (curframe->ready) { if (curframe->sequence_number != ab_read) { // some kind of sync problem has occurred. if (BUFIDX(curframe->sequence_number) == BUFIDX(ab_read)) { // it looks like some kind of aliasing has happened if (seq_order(ab_read, curframe->sequence_number)) { ab_read = curframe->sequence_number; debug(1, "Aliasing of buffer index -- reset."); } } else { debug(1, "Inconsistent sequence numbers detected"); } } if ((flush_rtp_timestamp != 0) && ((curframe->timestamp == flush_rtp_timestamp) || seq32_order(curframe->timestamp, flush_rtp_timestamp))) { debug(1, "Dropping flushed packet seqno %u, timestamp %u", curframe->sequence_number, curframe->timestamp); curframe->ready = 0; flush_limit++; ab_read = SUCCESSOR(ab_read); } if ((flush_rtp_timestamp != 0) && (!seq32_order(curframe->timestamp, flush_rtp_timestamp))) // if we have gone past the flush boundary time flush_rtp_timestamp = 0; } } while ((flush_rtp_timestamp != 0) && (flush_limit <= 8820) && (curframe->ready == 0)); if (flush_limit == 8820) { debug(1, "Flush hit the 8820 frame limit!"); flush_limit = 0; } curframe = audio_buffer + BUFIDX(ab_read); if (curframe->ready) { if (ab_buffering) { // if we are getting packets but not yet forwarding them to the player if (first_packet_timestamp == 0) { // if this is the very first packet // debug(1,"First frame seen, time %u, with %d // frames...",curframe->timestamp,seq_diff(ab_read, ab_write)); uint32_t reference_timestamp; uint64_t reference_timestamp_time,remote_reference_timestamp_time; get_reference_timestamp_stuff(&reference_timestamp, &reference_timestamp_time, &remote_reference_timestamp_time); if (reference_timestamp) { // if we have a reference time // debug(1,"First frame seen with timestamp..."); first_packet_timestamp = curframe->timestamp; // we will keep buffering until we are // supposed to start playing this // Here, calculate when we should start playing. We need to know when to allow the // packets to be sent to the player. // We will send packets of silence from now until that time and then we will send the // first packet, which will be followed by the subsequent packets. // we will get a fix every second or so, which will be stored as a pair consisting of // the time when the packet with a particular timestamp should be played, neglecting // latencies, etc. // It probably won't be the timestamp of our first packet, however, so we might have // to do some calculations. // To calculate when the first packet will be played, we figure out the exact time the // packet should be played according to its timestamp and the reference time. // We then need to add the desired latency, typically 88200 frames. // Then we need to offset this by the backend latency offset. For example, if we knew // that the audio back end has a latency of 100 ms, we would // ask for the first packet to be emitted 100 ms earlier than it should, i.e. -4410 // frames, so that when it got through the audio back end, // if would be in sync. To do this, we would give it a latency offset of -100 ms, i.e. // -4410 frames. int64_t delta = ((int64_t)first_packet_timestamp - (int64_t)reference_timestamp); first_packet_time_to_play = reference_timestamp_time + ((delta + (int64_t)config.latency + (int64_t)config.audio_backend_latency_offset) << 32) / 44100; if (local_time_now >= first_packet_time_to_play) { debug( 1, "First packet is late! It should have played before now. Flushing 0.1 seconds"); player_flush(first_packet_timestamp + 4410); } } } if (first_packet_time_to_play != 0) { uint32_t filler_size = frame_size; uint32_t max_dac_delay = 4410; filler_size = 4410; // 0.1 second -- the maximum we'll add to the DAC if (local_time_now >= first_packet_time_to_play) { // we've gone past the time... // debug(1,"Run past the exact start time by %llu frames, with time now of %llx, fpttp // of %llx and dac_delay of %d and %d packets; // flush.",(((tn-first_packet_time_to_play)*44100)>>32)+dac_delay,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read, // ab_write)); if (config.output->flush) config.output->flush(); ab_resync(); first_packet_timestamp = 0; first_packet_time_to_play = 0; time_since_play_started = 0; } else { if (config.output->delay) { dac_delay = config.output->delay(); if (dac_delay == -1) { debug(1, "Error getting dac_delay in buffer_get_frame."); dac_delay = 0; } } else dac_delay = 0; uint64_t gross_frame_gap = ((first_packet_time_to_play - local_time_now) * 44100) >> 32; int64_t exact_frame_gap = gross_frame_gap - dac_delay; if (exact_frame_gap <= 0) { // we've gone past the time... // debug(1,"Run a bit past the exact start time by %lld frames, with time now of // %llx, fpttp of %llx and dac_delay of %d and %d packets; // flush.",-exact_frame_gap,tn,first_packet_time_to_play,dac_delay,seq_diff(ab_read, // ab_write)); if (config.output->flush) config.output->flush(); ab_resync(); first_packet_timestamp = 0; first_packet_time_to_play = 0; } else { uint32_t fs = filler_size; if (fs > (max_dac_delay - dac_delay)) fs = max_dac_delay - dac_delay; if ((exact_frame_gap <= fs) || (exact_frame_gap <= frame_size * 2)) { fs = exact_frame_gap; // debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d, // with %d packets, ab_read is %04x, ab_write is // %04x.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read, // ab_write),ab_read,ab_write); ab_buffering = 0; } signed short *silence; silence = malloc(FRAME_BYTES(fs)); memset(silence, 0, FRAME_BYTES(fs)); // debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d, // with %d packets.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read, ab_write)); config.output->play(silence, fs); free(silence); if (ab_buffering == 0) { uint64_t reference_timestamp_time; // don't need this... get_reference_timestamp_stuff(&play_segment_reference_frame, &reference_timestamp_time, &play_segment_reference_frame_remote_time); #ifdef CONFIG_METADATA send_ssnc_metadata('prsm', NULL, 0, 0); // "resume", but don't wait if the queue is locked #endif } } } } } } } // Here, we work out whether to release a packet or wait // We release a buffer when the time is right. // To work out when the time is right, we need to take account of (1) the actual time the packet // should be released, // (2) the latency requested, (3) the audio backend latency offset and (4) the desired length of // the audio backend's buffer // The time is right if the current time is later or the same as // The packet time + (latency + latency offset - backend_buffer_length). // Note: the last three items are expressed in frames and must be converted to time. int do_wait = 1; if ((ab_synced) && (curframe) && (curframe->ready) && (curframe->timestamp)) { uint32_t reference_timestamp; uint64_t reference_timestamp_time,remote_reference_timestamp_time; get_reference_timestamp_stuff(&reference_timestamp, &reference_timestamp_time, &remote_reference_timestamp_time); if (reference_timestamp) { // if we have a reference time uint32_t packet_timestamp = curframe->timestamp; int64_t delta = ((int64_t)packet_timestamp - (int64_t)reference_timestamp); int64_t offset = (int64_t)config.latency + config.audio_backend_latency_offset - (int64_t)config.audio_backend_buffer_desired_length; int64_t net_offset = delta + offset; int64_t time_to_play = reference_timestamp_time; int64_t net_offset_fp_sec; if (net_offset >= 0) { net_offset_fp_sec = (net_offset << 32) / 44100; time_to_play += net_offset_fp_sec; // using the latency requested... // debug(2,"Net Offset: %lld, adjusted: %lld.",net_offset,net_offset_fp_sec); } else { net_offset_fp_sec = ((-net_offset) << 32) / 44100; time_to_play -= net_offset_fp_sec; // debug(2,"Net Offset: %lld, adjusted: -%lld.",net_offset,net_offset_fp_sec); } if (local_time_now >= time_to_play) { do_wait = 0; } } } wait = (ab_buffering || (do_wait != 0) || (!ab_synced)) && (!please_stop); if (wait) { uint64_t time_to_wait_for_wakeup_fp = ((uint64_t)1 << 32) / 44100; // this is time period of one frame time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time #ifdef COMPILE_FOR_LINUX_AND_FREEBSD uint64_t time_of_wakeup_fp = local_time_now + time_to_wait_for_wakeup_fp; uint64_t sec = time_of_wakeup_fp >> 32; uint64_t nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32; struct timespec time_of_wakeup; time_of_wakeup.tv_sec = sec; time_of_wakeup.tv_nsec = nsec; pthread_cond_timedwait(&flowcontrol, &ab_mutex, &time_of_wakeup); // int rc = pthread_cond_timedwait(&flowcontrol,&ab_mutex,&time_of_wakeup); // if (rc!=0) // debug(1,"pthread_cond_timedwait returned error code %d.",rc); #endif #ifdef COMPILE_FOR_OSX uint64_t sec = time_to_wait_for_wakeup_fp >> 32; ; uint64_t nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32; struct timespec time_to_wait; time_to_wait.tv_sec = sec; time_to_wait.tv_nsec = nsec; pthread_cond_timedwait_relative_np(&flowcontrol, &ab_mutex, &time_to_wait); #endif } } while (wait);
void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len) { pthread_mutex_lock(&ab_mutex); packet_count++; time_of_last_audio_packet = get_absolute_time_in_fp(); if (connection_state_to_output) { // if we are supposed to be processing these packets if ((flush_rtp_timestamp != 0) && ((timestamp == flush_rtp_timestamp) || seq32_order(timestamp, flush_rtp_timestamp))) { debug(2, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %u, flushing to " "timestamp: %u.", seqno, timestamp, flush_rtp_timestamp); } else { if ((flush_rtp_timestamp != 0x0) && (!seq32_order(timestamp, flush_rtp_timestamp))) // if we have gone past the flush boundary time flush_rtp_timestamp = 0x0; abuf_t *abuf = 0; if (!ab_synced) { debug(2, "syncing to seqno %u.", seqno); ab_write = seqno; ab_read = seqno; ab_synced = 1; } if (ab_write == seqno) { // expected packet abuf = audio_buffer + BUFIDX(seqno); ab_write = SUCCESSOR(seqno); } else if (seq_order(ab_write, seqno)) { // newer than expected // if (ORDINATE(seqno)>(BUFFER_FRAMES*7)/8) // debug(1,"An interval of %u frames has opened, with ab_read: %u, ab_write: %u and seqno: // %u.",seq_diff(ab_read,seqno),ab_read,ab_write,seqno); int32_t gap = seq_diff(ab_write, PREDECESSOR(seqno)) + 1; if (gap <= 0) debug(1, "Unexpected gap size: %d.", gap); int i; for (i = 0; i < gap; i++) { abuf = audio_buffer + BUFIDX(seq_sum(ab_write, i)); abuf->ready = 0; // to be sure, to be sure abuf->timestamp = 0; abuf->sequence_number = 0; } // debug(1,"N %d s %u.",seq_diff(ab_write,PREDECESSOR(seqno))+1,ab_write); abuf = audio_buffer + BUFIDX(seqno); rtp_request_resend(ab_write, gap); resend_requests++; ab_write = SUCCESSOR(seqno); } else if (seq_order(ab_read, seqno)) { // late but not yet played late_packets++; abuf = audio_buffer + BUFIDX(seqno); } else { // too late. too_late_packets++; /* if (!late_packet_message_sent) { debug(1, "too-late packet received: %u; ab_read: %u; ab_write: %u.", seqno, ab_read, ab_write); late_packet_message_sent=1; } */ } // pthread_mutex_unlock(&ab_mutex); if (abuf) { alac_decode(abuf->data, data, len); abuf->ready = 1; abuf->timestamp = timestamp; abuf->sequence_number = seqno; } // pthread_mutex_lock(&ab_mutex); } int rc = pthread_cond_signal(&flowcontrol); if (rc) debug(1, "Error signalling flowcontrol."); } pthread_mutex_unlock(&ab_mutex); }
static inline void buffer_put_packet(seq_t seqno, char *data, int len) { abuf_t *abuf = 0; abuf_t *tmpbuf = 0; unsigned short buf_fill; pthread_mutex_lock(&ab_mutex); /* sync is required. */ if (!ab_synced) { ab_write = seqno; if (seqno == 0) { ab_read = 0; } else { ab_read = seqno-1; } ab_synced = 1; } /* Check seq_no is what we want. */ buf_fill=BUF_FILL_SIZE(seqno,ab_read); if (buf_fill > 1000) { pthread_mutex_unlock(&ab_mutex); return; } /* Check buf slot is occupied. */ tmpbuf = audio_buffer + BUFIDX(seqno); // buffering fits here! if (tmpbuf->ready) { pthread_mutex_unlock(&ab_mutex); return; } /* if seqno moves faster than expected. */ if (seq_order(ab_write, seqno)) { // late but not yet played rtp_request_resend(ab_write+1, seqno-1); } /* update ab_write */ ab_write = seqno; abuf = audio_buffer + BUFIDX(seqno); // buffering fits here! /* Make sure the slot of abuf is empty! */ if (!abuf->ready) { memcpy(abuf->data, data, len); abuf->len=len; abuf->ready = 1; } buf_fill=BUF_FILL_SIZE(ab_write,ab_read); #ifdef DEBUG fprintf(stderr,"seqno=%d ab_write=%d ab_read=%d buf_fill=%d ab_buffering=%d \n",seqno,ab_write,ab_read,buf_fill,ab_buffering); #endif if (ab_buffering && (buf_fill >= (buffer_start_fill-1))) { ab_buffering = 0; pthread_cond_signal(&ab_buffer_ready); } if (buf_fill >= (BUFFER_FRAMES-1)) { // overrunning! #ifdef DEBUG fprintf(stderr,"overrunning.\n"); #endif pthread_cond_wait(&ab_buffer_full, &ab_mutex); buf_fill=BUF_FILL_SIZE(ab_write,ab_read); } pthread_mutex_unlock(&ab_mutex); }