Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
// 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;
}
Exemplo n.º 3
0
// 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;
}
Exemplo n.º 4
0
// 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;
}
Exemplo n.º 5
0
// 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;
}
Exemplo n.º 6
0
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;
        }
    }
}
Exemplo n.º 7
0
// 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++;
    }
}
Exemplo n.º 8
0
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);
}
Exemplo n.º 9
0
// 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;
    }
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
// 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);
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
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);
}