static int stream_sock_alloc(struct stream *s, int af) { struct sa laddr; int tos, err; if (!s) return EINVAL; /* we listen on all interfaces */ sa_init(&laddr, af); err = rtp_listen(&s->rtp, IPPROTO_UDP, &laddr, s->cfg.rtp_ports.min, s->cfg.rtp_ports.max, s->rtcp, rtp_recv, rtcp_handler, s); if (err) { warning("stream: rtp_listen failed: af=%s ports=%u-%u" " (%m)\n", net_af2name(af), s->cfg.rtp_ports.min, s->cfg.rtp_ports.max, err); return err; } tos = s->cfg.rtp_tos; (void)udp_setsockopt(rtp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); (void)udp_setsockopt(rtcp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); udp_rxsz_set(rtp_sock(s->rtp), RTP_RECV_SIZE); return 0; }
static int stream_sock_alloc(struct stream *s, int af) { struct sa laddr; int tos, err; if (!s) return EINVAL; /* we listen on all interfaces */ sa_init(&laddr, sa_af(net_laddr_af(af))); err = rtp_listen(&s->rtp, IPPROTO_UDP, &laddr, config.avt.rtp_ports.min, config.avt.rtp_ports.max, s->rtcp, rtp_recv, rtcp_handler, s); if (err) return err; tos = config.avt.rtp_tos; (void)udp_setsockopt(rtp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); (void)udp_setsockopt(rtcp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); udp_rxsz_set(rtp_sock(s->rtp), RTP_RECV_SIZE); return 0; }
void stream_update(struct stream *s) { const struct sdp_format *fmt; int err = 0; if (!s) return; fmt = sdp_media_rformat(s->sdp, NULL); s->pt_enc = fmt ? fmt->pt : -1; if (sdp_media_has_media(s->sdp)) stream_remote_set(s); if (s->menc && s->menc->mediah) { err = s->menc->mediah(&s->mes, s->mencs, s->rtp, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); if (err) { warning("stream: mediaenc update: %m\n", err); } } }
void stream_update(struct stream *s, const char *cname) { const struct sdp_format *fmt; int err = 0; if (!s) return; fmt = sdp_media_rformat(s->sdp, NULL); s->pt_enc = fmt ? fmt->pt : -1; if (stream_has_media(s)) stream_remote_set(s, cname); if (s->menc && s->menc->mediah) { err = s->menc->mediah(&s->mes, s->mencs, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); if (err) { DEBUG_WARNING("mediaenc update: %m\n", err); } } }
int stream_alloc(struct stream **sp, const struct config_avt *cfg, struct call *call, struct sdp_session *sdp_sess, const char *name, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, const char *cname, stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg) { struct stream *s; int err; if (!sp || !cfg || !call || !rtph) return EINVAL; s = mem_zalloc(sizeof(*s), stream_destructor); if (!s) return ENOMEM; s->cfg = *cfg; s->call = call; s->rtph = rtph; s->rtcph = rtcph; s->arg = arg; s->pseq = -1; s->rtcp = s->cfg.rtcp_enable; err = stream_sock_alloc(s, call_af(call)); if (err) { warning("stream: failed to create socket for media '%s'" " (%m)\n", name, err); goto out; } err = str_dup(&s->cname, cname); if (err) goto out; /* Jitter buffer */ if (cfg->jbuf_del.min && cfg->jbuf_del.max) { err = jbuf_alloc(&s->jbuf, cfg->jbuf_del.min, cfg->jbuf_del.max); if (err) goto out; } err = sdp_media_add(&s->sdp, sdp_sess, name, sa_port(rtp_local(s->rtp)), (menc && menc->sdp_proto) ? menc->sdp_proto : sdp_proto_rtpavp); if (err) goto out; if (label) { err |= sdp_media_set_lattr(s->sdp, true, "label", "%d", label); } /* RFC 5506 */ if (s->rtcp) err |= sdp_media_set_lattr(s->sdp, true, "rtcp-rsize", NULL); /* RFC 5576 */ if (s->rtcp) { err |= sdp_media_set_lattr(s->sdp, true, "ssrc", "%u cname:%s", rtp_sess_ssrc(s->rtp), cname); } /* RFC 5761 */ if (cfg->rtcp_mux) err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL); if (err) goto out; if (mnat) { err = mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); if (err) goto out; } if (menc) { s->menc = menc; s->mencs = mem_ref(menc_sess); err = menc->mediah(&s->mes, menc_sess, s->rtp, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); if (err) goto out; } if (err) goto out; s->pt_enc = -1; metric_init(&s->metric_tx); metric_init(&s->metric_rx); list_append(call_streaml(call), &s->le, s); out: if (err) mem_deref(s); else *sp = s; return err; }
int stream_alloc(struct stream **sp, struct call *call, struct sdp_session *sdp_sess, const char *name, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg) { struct stream *s; int err; if (!sp || !call || !rtph) return EINVAL; s = mem_zalloc(sizeof(*s), stream_destructor); if (!s) return ENOMEM; MAGIC_INIT(s); tmr_init(&s->tmr_stats); s->call = call; if (!str_casecmp(name, "audio")) s->type = STREAM_AUDIO; else if (!str_casecmp(name, "video")) s->type = STREAM_VIDEO; else s->type = STREAM_UNKNOWN; s->rtph = rtph; s->rtcph = rtcph; s->arg = arg; s->pseq = -1; s->rtcp = config.avt.rtcp_enable; err = stream_sock_alloc(s, call_af(call)); if (err) goto out; /* Jitter buffer */ if (config.avt.jbuf_del.min && config.avt.jbuf_del.max) { err = jbuf_alloc(&s->jbuf, config.avt.jbuf_del.min, config.avt.jbuf_del.max); if (err) goto out; } err = sdp_media_add(&s->sdp, sdp_sess, name, sa_port(rtp_local(s->rtp)), (menc && menc->sdp_proto) ? menc->sdp_proto : sdp_proto_rtpavp); if (err) goto out; if (label) { err |= sdp_media_set_lattr(s->sdp, true, "label", "%d", label); } /* RFC 5761 */ if (config.avt.rtcp_mux) err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL); if (mnat) { err |= mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP, rtp_sock(s->rtp), (s->rtcp && !config.avt.rtcp_mux) ? rtcp_sock(s->rtp) : NULL, s->sdp); } if (menc) { s->menc = menc; s->mencs = mem_ref(menc_sess); err |= menc->mediah(&s->mes, menc_sess, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); } if (err) goto out; s->pt_enc = -1; list_append(call_streaml(call), &s->le, s); out: if (err) mem_deref(s); else *sp = s; return err; }