diff --git a/daemon/call.h b/daemon/call.h index 12a53292d..254065924 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -282,7 +282,7 @@ struct packet_stream { struct endpoint endpoint; /* LOCK: out_lock */ struct endpoint advertised_endpoint; /* RO */ struct crypto_context crypto; /* OUT direction, LOCK: out_lock */ - struct ssrc_ctx *ssrc_in, /* LOCK: in_lock */ + struct ssrc_ctx *ssrc_in, /* LOCK: in_lock */ // XXX eliminate these *ssrc_out; /* LOCK: out_lock */ struct stats stats; @@ -340,7 +340,7 @@ struct call_media { GQueue codecs_prefs_send; // storage container GHashTable *codec_handlers; // int payload type -> struct codec_handler - // XXX combine this with 'codecs' hash table? + // XXX combine this with 'codecs_recv' hash table? volatile struct codec_handler *codec_handler_cache; int ptime; // either from SDP or overridden diff --git a/daemon/codec.c b/daemon/codec.c index b09d49ff8..7fed58813 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -21,7 +21,6 @@ struct codec_ssrc_handler { int ptime; int bytes_per_packet; unsigned long ts_out; - u_int32_t ssrc_out; u_int16_t seq_out; GString *sample_buffer; }; @@ -368,12 +367,12 @@ void codec_handlers_free(struct call_media *m) { static int handler_func_passthrough(struct codec_handler *h, struct call_media *media, - const struct media_packet *mp, GQueue *out) + struct media_packet *mp) { struct codec_packet *p = g_slice_alloc(sizeof(*p)); p->s = mp->raw; p->free_func = NULL; - g_queue_push_tail(out, p); + g_queue_push_tail(&mp->packets_out, p); return 0; } @@ -385,13 +384,11 @@ static void __transcode_packet_free(struct transcode_packet *p) { static struct ssrc_entry *__ssrc_handler_new(void *p) { struct codec_handler *h = p; - u_int32_t ssrc_out = random(); ilog(LOG_DEBUG, "Creating SSRC transcoder from %s/%u/%i to " - "SSRC %" PRIx32 " %s/%u/%i", + "%s/%u/%i", h->source_pt.codec_def->rtpname, h->source_pt.clock_rate, h->source_pt.channels, - ntohl(ssrc_out), h->dest_pt.codec_def->rtpname, h->dest_pt.clock_rate, h->dest_pt.channels); @@ -400,7 +397,6 @@ static struct ssrc_entry *__ssrc_handler_new(void *p) { mutex_init(&ch->lock); packet_sequencer_init(&ch->sequencer, (GDestroyNotify) __transcode_packet_free); ch->seq_out = random(); - ch->ssrc_out = ssrc_out; ch->ts_out = random(); ch->ptime = h->dest_pt.ptime; ch->sample_buffer = g_string_new(""); @@ -461,7 +457,7 @@ static void __ssrc_handler_free(struct codec_ssrc_handler *ch) { static int __packet_encoded(encoder_t *enc, void *u1, void *u2) { struct codec_ssrc_handler *ch = u1; - GQueue *out_q = u2; + struct media_packet *mp = u2; ilog(LOG_DEBUG, "RTP media successfully encoded: TS %llu, len %i", (unsigned long long) enc->avpkt.pts, enc->avpkt.size); @@ -499,14 +495,14 @@ static int __packet_encoded(encoder_t *enc, void *u1, void *u2) { rh->m_pt = ch->handler->dest_pt.payload_type; rh->seq_num = htons(ch->seq_out++); rh->timestamp = htonl(enc->avpkt.pts + ch->ts_out); - rh->ssrc = ch->ssrc_out; + rh->ssrc = mp->ssrc_out->ssrc_map_out; // add to output queue struct codec_packet *p = g_slice_alloc(sizeof(*p)); p->s.s = buf; p->s.len = inout.len + sizeof(struct rtp_header); p->free_func = free; - g_queue_push_tail(out_q, p); + g_queue_push_tail(&mp->packets_out, p); if (ret == 0) { // no more to go @@ -533,10 +529,10 @@ static int __packet_decoded(decoder_t *decoder, AVFrame *frame, void *u1, void * } static int handler_func_transcode(struct codec_handler *h, struct call_media *media, - const struct media_packet *mp, GQueue *out) + struct media_packet *mp) { if (G_UNLIKELY(!mp->rtp || mp->rtcp)) - return handler_func_passthrough(h, media, mp, out); + return handler_func_passthrough(h, media, mp); assert((mp->rtp->m_pt & 0x7f) == h->source_pt.payload_type); @@ -575,7 +571,7 @@ static int handler_func_transcode(struct codec_handler *h, struct call_media *me ilog(LOG_DEBUG, "Decoding RTP packet: seq %u, TS %lu", packet->p.seq, packet->ts); - if (decoder_input_data(ch->decoder, packet->payload, packet->ts, __packet_decoded, ch, out)) + if (decoder_input_data(ch->decoder, packet->payload, packet->ts, __packet_decoded, ch, mp)) ilog(LOG_WARN, "Decoder error while processing RTP packet"); __transcode_packet_free(packet); } diff --git a/daemon/codec.h b/daemon/codec.h index 0d52bd048..3852ad40f 100644 --- a/daemon/codec.h +++ b/daemon/codec.h @@ -15,8 +15,7 @@ struct media_packet; struct ssrc_hash; -typedef int codec_handler_func(struct codec_handler *, struct call_media *, const struct media_packet *, - GQueue *); +typedef int codec_handler_func(struct codec_handler *, struct call_media *, struct media_packet *); struct codec_handler { diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 7b8f64957..de4758638 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -70,7 +70,6 @@ struct packet_handler_ctx { rewrite_func decrypt_func, encrypt_func; // handlers for decrypt/encrypt struct packet_stream *in_srtp, *out_srtp; // SRTP contexts for decrypt/encrypt (relevant for muxed RTCP) int payload_type; // -1 if unknown or not RTP - struct ssrc_ctx *ssrc_in, *ssrc_out; // SSRC contexts from in_srtp and out_srtp int rtcp; // true if this is an RTCP packet // verdicts: @@ -80,7 +79,6 @@ struct packet_handler_ctx { // output: struct media_packet mp; // passed to handlers - GQueue packets_out; }; @@ -1182,6 +1180,9 @@ static void __stream_ssrc(struct packet_stream *in_srtp, struct packet_stream *o mutex_unlock(&in_srtp->in_lock); + if (MEDIA_ISSET(in_srtp->media, TRANSCODE)) + ssrc = (*ssrc_in_p)->ssrc_map_out; + // out direction mutex_lock(&out_srtp->out_lock); @@ -1297,14 +1298,14 @@ static void media_packet_rtp(struct packet_handler_ctx *phc) rtp_padding(phc->mp.rtp, &phc->mp.payload); if (G_LIKELY(phc->out_srtp != NULL)) - __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtp->ssrc, &phc->ssrc_in, - &phc->ssrc_out, phc->call->ssrc_hash); + __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtp->ssrc, &phc->mp.ssrc_in, + &phc->mp.ssrc_out, phc->call->ssrc_hash); // check the payload type // XXX redundant between SSRC handling and codec_handler stuff -> combine phc->payload_type = (phc->mp.rtp->m_pt & 0x7f); - if (G_LIKELY(phc->ssrc_in)) - phc->ssrc_in->parent->payload_type = phc->payload_type; + if (G_LIKELY(phc->mp.ssrc_in)) + phc->mp.ssrc_in->parent->payload_type = phc->payload_type; // XXX convert to array? or keep last pointer? // XXX yet another hash table per payload type -> combine @@ -1323,8 +1324,8 @@ static void media_packet_rtp(struct packet_handler_ctx *phc) } else if (phc->rtcp && !rtcp_payload(&phc->mp.rtcp, NULL, &phc->s)) { if (G_LIKELY(phc->out_srtp != NULL)) - __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtcp->ssrc, &phc->ssrc_in, - &phc->ssrc_out, phc->call->ssrc_hash); + __stream_ssrc(phc->in_srtp, phc->out_srtp, phc->mp.rtcp->ssrc, &phc->mp.ssrc_in, + &phc->mp.ssrc_out, phc->call->ssrc_hash); } } @@ -1348,7 +1349,7 @@ static int media_packet_decrypt(struct packet_handler_ctx *phc) * 1 = forward and push update to redis */ int ret = 0; if (phc->decrypt_func) - ret = phc->decrypt_func(&phc->s, phc->in_srtp, phc->sfd, &phc->fsin, &phc->tv, phc->ssrc_in); + ret = phc->decrypt_func(&phc->s, phc->in_srtp, phc->sfd, &phc->fsin, &phc->tv, phc->mp.ssrc_in); mutex_unlock(&phc->in_srtp->in_lock); @@ -1367,9 +1368,9 @@ static int media_packet_encrypt(struct packet_handler_ctx *phc) { mutex_lock(&phc->out_srtp->out_lock); - for (GList *l = phc->packets_out.head; l; l = l->next) { + for (GList *l = phc->mp.packets_out.head; l; l = l->next) { struct codec_packet *p = l->data; - int encret = phc->encrypt_func(&p->s, phc->out_srtp, NULL, NULL, NULL, phc->ssrc_out); + int encret = phc->encrypt_func(&p->s, phc->out_srtp, NULL, NULL, NULL, phc->mp.ssrc_out); if (encret == 1) phc->update = 1; else if (encret != 0) @@ -1599,7 +1600,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { struct codec_handler *transcoder = codec_handler_get(phc->media, phc->payload_type); // this transfers the packet from 's' to 'packets_out' phc->mp.raw = phc->s; - if (transcoder->func(transcoder, phc->media, &phc->mp, &phc->packets_out)) + if (transcoder->func(transcoder, phc->media, &phc->mp)) goto drop; if (G_LIKELY(handler_ret >= 0)) @@ -1630,7 +1631,7 @@ static int stream_packet(struct packet_handler_ctx *phc) { struct codec_packet *p; ret = 0; - while ((p = g_queue_pop_head(&phc->packets_out))) { + while ((p = g_queue_pop_head(&phc->mp.packets_out))) { __C_DBG("Forward to sink endpoint: %s:%d", sockaddr_print_buf(&phc->sink->endpoint.address), phc->sink->endpoint.port); @@ -1670,7 +1671,7 @@ out: rwlock_unlock_r(&phc->call->master_lock); - g_queue_clear_full(&phc->packets_out, codec_packet_free); + g_queue_clear_full(&phc->mp.packets_out, codec_packet_free); return ret; } diff --git a/daemon/media_socket.h b/daemon/media_socket.h index 3d25eeba8..1f1e1c662 100644 --- a/daemon/media_socket.h +++ b/daemon/media_socket.h @@ -72,7 +72,10 @@ struct media_packet { str raw; struct rtp_header *rtp; struct rtcp_packet *rtcp; + struct ssrc_ctx *ssrc_in, *ssrc_out; // SSRC contexts from in_srtp and out_srtp str payload; + + GQueue packets_out; }; diff --git a/daemon/ssrc.c b/daemon/ssrc.c index cb38fbc99..3edce4467 100644 --- a/daemon/ssrc.c +++ b/daemon/ssrc.c @@ -8,6 +8,7 @@ static void init_ssrc_ctx(struct ssrc_ctx *c, struct ssrc_entry_call *parent) { c->parent = parent; + c->ssrc_map_out = random(); } static void init_ssrc_entry(struct ssrc_entry *ent, u_int32_t ssrc) { ent->ssrc = ssrc; diff --git a/daemon/ssrc.h b/daemon/ssrc.h index 26111c9c6..249220913 100644 --- a/daemon/ssrc.h +++ b/daemon/ssrc.h @@ -40,6 +40,7 @@ struct ssrc_ctx { u_int64_t srtp_index, srtcp_index; // XXX move entire crypto context in here? + u_int32_t ssrc_map_out; }; struct ssrc_stats_block {