Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions daemon/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ struct codec_ssrc_handler {
uint64_t skip_pts;

bool rtp_mark;
bool decode_only; // consumes without replacing: doesn't move the seq offset
};
struct transcode_packet {
seq_packet_t p; // must be first
Expand Down Expand Up @@ -2429,7 +2430,8 @@ static int __handler_func_sequencer(struct media_packet *mp, struct transcode_pa

if (seq_ret == 1) {
// seq reset - update output seq. we keep our output seq clean
ssrc_out->seq_diff -= packet->p.seq - seq_ori;
if (!ch->decode_only)
ssrc_out->seq_diff -= packet->p.seq - seq_ori;
seq_ret = 0;
}

Expand Down Expand Up @@ -4029,7 +4031,7 @@ static void __dtx_send_later(struct codec_timer *ct) {
// release and try again
mutex_unlock(&dtxb->lock);

if (call && mp_copy.ssrc_out) {
if (call && mp_copy.ssrc_out && !ch->decode_only) {
// packet consumed - track seq
rwlock_lock_r(&call->master_lock);
__ssrc_lock_both(&mp_copy);
Expand Down Expand Up @@ -4542,6 +4544,7 @@ static struct ssrc_entry *__ssrc_handler_decode_new(void *p) {

__auto_type ch = obj_alloc0(struct codec_ssrc_handler, __free_ssrc_handler);
ch->handler = h;
ch->decode_only = true;
ch->ptime = h->dest_pt.ptime;

format_t dest_format = {
Expand Down Expand Up @@ -4897,7 +4900,8 @@ static tc_code __rtp_decode_direct(struct codec_ssrc_handler *ch, struct codec_s
code = ret == 0 ? TCC_OK : TCC_ERR;
}
}
__buffer_delay_seq(input_ch->handler->delay_buffer, mp, -1);
if (!ch->decode_only) // consumed, not replaced: doesn't count towards the seq offset
__buffer_delay_seq(input_ch->handler->delay_buffer, mp, -1);
return code;
}
static tc_code __rtp_decode_async(struct codec_ssrc_handler *ch, struct codec_ssrc_handler *input_ch,
Expand Down
52 changes: 38 additions & 14 deletions daemon/media_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,11 @@ static const char *kernelize_target(kernelize_state *s, struct packet_stream *st
return NULL;
}

// the kernel's ssrc_subst cases: echo, transcoding or a fixed egress SSRC
static bool sink_substitutes_ssrc(struct call_media *in, const struct sink_handler *sh, struct call_media *out) {
return MEDIA_ISSET(in, ECHO) || sh->attrs.transcoding || (out && out->fixed_egress_ssrc);
}

/**
* The linkage between userspace and kernel module is in the kernelize_one().
*
Expand Down Expand Up @@ -1889,8 +1894,7 @@ static const char *kernelize_one(kernelize_state *s,

}

if (MEDIA_ISSET(media, ECHO) || sink_handler->attrs.transcoding
|| sink->media->fixed_egress_ssrc)
if (sink_substitutes_ssrc(media, sink_handler, sink->media))
redi->output.ssrc_subst = 1;

__re_address_translate_ep(&redi->output.dst_addr, &sink->endpoint);
Expand Down Expand Up @@ -2623,7 +2627,7 @@ const struct streamhandler *determine_sink_handler(struct packet_stream *in, str
must_recrypt = true;
else if (ML_ISSET(in->media->monologue, INJECT_DTMF) || (out && ML_ISSET(out->media->monologue, INJECT_DTMF)))
must_recrypt = true;
else if (sh->attrs.transcoding)
else if (sink_substitutes_ssrc(media_in, sh, media_out)) // the header is rewritten: the packet is encrypted anew
must_recrypt = true;
else if (in->call->recording)
must_recrypt = true;
Expand Down Expand Up @@ -3487,6 +3491,22 @@ void media_packet_release(struct media_packet *mp) {
}


// gives a sink its own copy of the packet to rewrite, with the header, payload and extensions pointing into it
static void media_packet_sink_copy(struct media_packet *mp, GQueue *free_list) {
char *buf = bufferpool_alloc(media_bufferpool, mp->raw.len + RTP_BUFFER_TAIL_ROOM);
memcpy(buf, mp->raw.s, mp->raw.len);
g_queue_push_tail(free_list, buf);
if (mp->rtp)
mp->rtp = (void *) (buf + ((char *) mp->rtp - mp->raw.s));
if (mp->rtcp)
mp->rtcp = (void *) (buf + ((char *) mp->rtcp - mp->raw.s));
if (mp->payload.s)
mp->payload.s = buf + (mp->payload.s - mp->raw.s);
if (mp->extensions.s)
mp->extensions.s = buf + (mp->extensions.s - mp->raw.s);
mp->raw.s = buf;
}

static int media_packet_queue_dup(codec_packet_q *q) {
IQUEUE_FOREACH(q, p) {
if (p->free_func) // nothing to do, already private
Expand Down Expand Up @@ -3661,12 +3681,26 @@ static int stream_packet(struct packet_handler_ctx *phc) {

///////////////// EGRESS HANDLING

str orig_raw = STR_NULL;
// the handlers may rewrite the packet in place, but we may have multiple outputs: every sink
// starts from the packet as received and gets its own copy of it unless it's the last one
const str orig_raw = phc->mp.raw;
struct rtp_header *const orig_rtp = phc->mp.rtp;
struct rtcp_packet *const orig_rtcp = phc->mp.rtcp;
const str orig_payload = phc->mp.payload;
const str orig_extensions = phc->mp.extensions;

for (__auto_type sh_link = phc->sinks->head; sh_link; sh_link = sh_link->next) {
struct sink_handler *sh = sh_link->data;
struct packet_stream *sink = sh->bundle_sink;

phc->mp.raw = orig_raw;
phc->mp.rtp = orig_rtp;
phc->mp.rtcp = orig_rtcp;
phc->mp.payload = orig_payload;
phc->mp.extensions = orig_extensions;
if (sh_link->next)
media_packet_sink_copy(&phc->mp, &free_list);

// this sets rtcp, in_srtp, out_srtp, media_out, and sink
media_packet_rtcp_mux(phc, sh);

Expand All @@ -3678,16 +3712,6 @@ static int stream_packet(struct packet_handler_ctx *phc) {
if (phc->rtcp) {
phc->rtcp_discard = false;
handler_ret = -1;
// these functions may do in-place rewriting, but we may have multiple
// outputs - make a copy if this isn't the last sink
if (sh_link->next) {
if (!orig_raw.s)
orig_raw = phc->mp.raw;
char *buf = bufferpool_alloc(media_bufferpool, orig_raw.len + RTP_BUFFER_TAIL_ROOM);
memcpy(buf, orig_raw.s, orig_raw.len);
phc->mp.raw.s = buf;
g_queue_push_tail(&free_list, buf);
}
if (do_rtcp_parse(phc))
goto out;
if (phc->rtcp_discard)
Expand Down
Loading
Loading