Ejemplo 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);
}
Ejemplo n.º 2
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;
}
Ejemplo 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.");
        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;
}
Ejemplo n.º 4
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++;
    }
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
Archivo: rtp.c Proyecto: viettd56/SA
void rtp_request_resend(seq_t first, seq_t last) {
    if (!running)
        die("rtp_request_resend called without active stream!");

    debug(1, "requesting resend on %d packets (%04X:%04X)\n",
         seq_diff(first,last) + 1, first, last);

    char req[8];    // *not* a standard RTCP NACK
    req[0] = 0x80;
    req[1] = 0x55|0x80;  // Apple 'resend'
    *(unsigned short *)(req+2) = htons(1);  // our seqnum
    *(unsigned short *)(req+4) = htons(first);  // missed seqnum
    *(unsigned short *)(req+6) = htons(last-first+1);  // count

    sendto(sock, req, sizeof(req), 0, (struct sockaddr*)&rtp_client, sizeof(rtp_client));
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
0
int srtp_decrypt(struct srtp *srtp, struct mbuf *mb)
{
	struct srtp_stream *strm;
	struct rtp_header hdr;
	struct comp *comp;
	uint64_t ix;
	size_t start;
	int diff;
	int err;

	if (!srtp || !mb)
		return EINVAL;

	comp = &srtp->rtp;

	start = mb->pos;

	err = rtp_hdr_decode(&hdr, mb);
	if (err)
		return err;

	err = stream_get_seq(&strm, srtp, hdr.ssrc, hdr.seq);
	if (err)
		return err;

	diff = seq_diff(strm->s_l, hdr.seq);
	if (diff > 32768)
		return ETIMEDOUT;

	/* Roll-Over Counter (ROC) */
	if (diff <= -32768) {
		strm->roc++;
		strm->s_l = 0;
	}

	ix = srtp_get_index(strm->roc, strm->s_l, hdr.seq);

	if (comp->hmac) {
		uint8_t tag_calc[SHA_DIGEST_LENGTH];
		uint8_t tag_pkt[SHA_DIGEST_LENGTH];
		size_t pld_start, tag_start;

		if (mbuf_get_left(mb) < comp->tag_len)
			return EBADMSG;

		pld_start = mb->pos;
		tag_start = mb->end - comp->tag_len;

		mb->pos = tag_start;

		err = mbuf_read_mem(mb, tag_pkt, comp->tag_len);
		if (err)
			return err;

		mb->pos = mb->end = tag_start;

		err = mbuf_write_u32(mb, htonl(strm->roc));
		if (err)
			return err;

		mb->pos = start;

		err = hmac_digest(comp->hmac, tag_calc, sizeof(tag_calc),
				  mbuf_buf(mb), mbuf_get_left(mb));
		if (err)
			return err;

		mb->pos = pld_start;
		mb->end = tag_start;

		if (0 != memcmp(tag_calc, tag_pkt, comp->tag_len))
			return EAUTH;

		/*
		 * 3.3.2.  Replay Protection
		 *
		 * Secure replay protection is only possible when
		 * integrity protection is present.
		 */
		if (!srtp_replay_check(&strm->replay_rtp, ix))
			return EALREADY;
	}

	if (comp->aes) {

		union vect128 iv;
		uint8_t *p = mbuf_buf(mb);

		srtp_iv_calc(&iv, &comp->k_s, strm->ssrc, ix);

		aes_set_iv(comp->aes, iv.u8);
		err = aes_decr(comp->aes, p, p, mbuf_get_left(mb));
		if (err)
			return err;
	}

	if (hdr.seq > strm->s_l)
		strm->s_l = hdr.seq;

	mb->pos = start;

	return 0;
}
Ejemplo n.º 9
0
int srtp_encrypt(struct srtp *srtp, struct mbuf *mb)
{
	struct srtp_stream *strm;
	struct rtp_header hdr;
	struct comp *comp;
	size_t start;
	uint64_t ix;
	int err;

	if (!srtp || !mb)
		return EINVAL;

	comp = &srtp->rtp;

	start = mb->pos;

	err = rtp_hdr_decode(&hdr, mb);
	if (err)
		return err;

	err = stream_get_seq(&strm, srtp, hdr.ssrc, hdr.seq);
	if (err)
		return err;

	/* Roll-Over Counter (ROC) */
	if (seq_diff(strm->s_l, hdr.seq) <= -32768) {
		strm->roc++;
		strm->s_l = 0;
	}

	ix = 65536ULL * strm->roc + hdr.seq;

	if (comp->aes) {
		union vect128 iv;
		uint8_t *p = mbuf_buf(mb);

		srtp_iv_calc(&iv, &comp->k_s, strm->ssrc, ix);

		aes_set_iv(comp->aes, iv.u8);
		err = aes_encr(comp->aes, p, p, mbuf_get_left(mb));
		if (err)
			return err;
	}

	if (comp->hmac) {
		const size_t tag_start = mb->end;
		uint8_t tag[SHA_DIGEST_LENGTH];

		mb->pos = tag_start;

		err = mbuf_write_u32(mb, htonl(strm->roc));
		if (err)
			return err;

		mb->pos = start;

		err = hmac_digest(comp->hmac, tag, sizeof(tag),
				  mbuf_buf(mb), mbuf_get_left(mb));
		if (err)
			return err;

		mb->pos = mb->end = tag_start;

		err = mbuf_write_mem(mb, tag, comp->tag_len);
		if (err)
			return err;
	}

	if (hdr.seq > strm->s_l)
		strm->s_l = hdr.seq;

	mb->pos = start;

	return 0;
}
Ejemplo n.º 10
0
int h265_decode(struct viddec_state *vds, struct vidframe *frame,
		bool marker, uint16_t seq, struct mbuf *mb)
{
	static const uint8_t nal_seq[3] = {0, 0, 1};
	int err, ret, got_picture, i;
	struct h265_nal hdr;
	AVPacket avpkt;
	enum vidfmt fmt;

	if (!vds || !frame || !mb)
		return EINVAL;

	err = h265_nal_decode(&hdr, mbuf_buf(mb));
	if (err)
		return err;

	mbuf_advance(mb, H265_HDR_SIZE);

#if 1
	debug("h265: decode: %s type=%2d  %s\n",
		  h265_is_keyframe(hdr.nal_unit_type) ? "<KEY>" : "     ",
		  hdr.nal_unit_type,
		  h265_nalunit_name(hdr.nal_unit_type));
#endif


	if (vds->frag && hdr.nal_unit_type != H265_NAL_FU) {
		debug("h265: lost fragments; discarding previous NAL\n");
		fragment_rewind(vds);
		vds->frag = false;
	}

	/* handle NAL types */
	if (0 <= hdr.nal_unit_type && hdr.nal_unit_type <= 40) {

		mb->pos -= H265_HDR_SIZE;

		err  = mbuf_write_mem(vds->mb, nal_seq, 3);
		err |= mbuf_write_mem(vds->mb, mbuf_buf(mb),mbuf_get_left(mb));
		if (err)
			goto out;
	}
	else if (H265_NAL_FU == hdr.nal_unit_type) {

		struct fu fu;

		err = fu_decode(&fu, mb);
		if (err)
			return err;

		if (fu.s) {
			if (vds->frag) {
				debug("h265: lost fragments; ignoring NAL\n");
				fragment_rewind(vds);
			}

			vds->frag_start = vds->mb->pos;
			vds->frag = true;

			hdr.nal_unit_type = fu.type;

			err  = mbuf_write_mem(vds->mb, nal_seq, 3);
			err = h265_nal_encode_mbuf(vds->mb, &hdr);
			if (err)
				goto out;
		}
		else {
			if (!vds->frag) {
				debug("h265: ignoring fragment\n");
				return 0;
			}

			if (seq_diff(vds->frag_seq, seq) != 1) {
				debug("h265: lost fragments detected\n");
				fragment_rewind(vds);
				vds->frag = false;
				return 0;
			}
		}

		err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb));
		if (err)
			goto out;

		if (fu.e)
			vds->frag = false;

		vds->frag_seq = seq;
	}
	else {
		warning("h265: unknown NAL type %u\n", hdr.nal_unit_type);
		return ENOSYS;
	}

	if (!marker) {

		if (vds->mb->end > DECODE_MAXSZ) {
			warning("h265: decode buffer size exceeded\n");
			err = ENOMEM;
			goto out;
		}

		return 0;
	}

	if (vds->frag) {
		err = EPROTO;
		goto out;
	}

	av_init_packet(&avpkt);
	avpkt.data = vds->mb->buf;
	avpkt.size = (int)vds->mb->end;

	ret = avcodec_decode_video2(vds->ctx, vds->pict, &got_picture, &avpkt);
	if (ret < 0) {
		debug("h265: decode error\n");
		err = EPROTO;
		goto out;
	}

	if (!got_picture) {
		/* debug("h265: no picture\n"); */
		goto out;
	}

	switch (vds->pict->format) {

	case PIX_FMT_YUV420P:
		fmt = VID_FMT_YUV420P;
		break;

#if 0
	case PIX_FMT_YUV444P:
		fmt = VID_FMT_YUV444;
		break;
#endif

	default:
		warning("h265: decode: bad pixel format (%i) (%s)\n",
			vds->pict->format,
			av_get_pix_fmt_name(vds->pict->format));
		goto out;
	}

	for (i=0; i<4; i++) {
		frame->data[i]     = vds->pict->data[i];
		frame->linesize[i] = vds->pict->linesize[i];
	}

	frame->size.w = vds->ctx->width;
	frame->size.h = vds->ctx->height;
	frame->fmt    = fmt;

 out:
	mbuf_rewind(vds->mb);
	vds->frag = false;

	return err;
}