|
|
|
@ -1353,10 +1353,11 @@ void free_sink_handler(void *p) {
|
|
|
|
struct sink_handler *sh = p;
|
|
|
|
struct sink_handler *sh = p;
|
|
|
|
g_slice_free1(sizeof(*sh), sh);
|
|
|
|
g_slice_free1(sizeof(*sh), sh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void __add_sink_handler(GQueue *q, struct packet_stream *sink) {
|
|
|
|
void __add_sink_handler(GQueue *q, struct packet_stream *sink, bool rtcp_only) {
|
|
|
|
struct sink_handler *sh = g_slice_alloc0(sizeof(*sh));
|
|
|
|
struct sink_handler *sh = g_slice_alloc0(sizeof(*sh));
|
|
|
|
sh->sink = sink;
|
|
|
|
sh->sink = sink;
|
|
|
|
sh->kernel_output_idx = -1;
|
|
|
|
sh->kernel_output_idx = -1;
|
|
|
|
|
|
|
|
sh->rtcp_only = rtcp_only ? 1 : 0;
|
|
|
|
g_queue_push_tail(q, sh);
|
|
|
|
g_queue_push_tail(q, sh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1372,7 +1373,7 @@ static void __reset_streams(struct call_media *media) {
|
|
|
|
// B can be NULL
|
|
|
|
// B can be NULL
|
|
|
|
// XXX this function seems to do two things - stream init (with B NULL) and sink init - split up?
|
|
|
|
// XXX this function seems to do two things - stream init (with B NULL) and sink init - split up?
|
|
|
|
static int __init_streams(struct call_media *A, struct call_media *B, const struct stream_params *sp,
|
|
|
|
static int __init_streams(struct call_media *A, struct call_media *B, const struct stream_params *sp,
|
|
|
|
const struct sdp_ng_flags *flags) {
|
|
|
|
const struct sdp_ng_flags *flags, bool rtcp_only) {
|
|
|
|
GList *la, *lb;
|
|
|
|
GList *la, *lb;
|
|
|
|
struct packet_stream *a, *ax, *b;
|
|
|
|
struct packet_stream *a, *ax, *b;
|
|
|
|
unsigned int port_off = 0;
|
|
|
|
unsigned int port_off = 0;
|
|
|
|
@ -1394,9 +1395,9 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
// we get SSRC flip-flops on the opposite side
|
|
|
|
// we get SSRC flip-flops on the opposite side
|
|
|
|
// XXX still necessary for blackhole?
|
|
|
|
// XXX still necessary for blackhole?
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE))
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE))
|
|
|
|
__add_sink_handler(&a->rtp_sinks, a);
|
|
|
|
__add_sink_handler(&a->rtp_sinks, a, rtcp_only);
|
|
|
|
else if (b)
|
|
|
|
else if (b)
|
|
|
|
__add_sink_handler(&a->rtp_sinks, b);
|
|
|
|
__add_sink_handler(&a->rtp_sinks, b, rtcp_only);
|
|
|
|
PS_SET(a, RTP); /* XXX technically not correct, could be udptl too */
|
|
|
|
PS_SET(a, RTP); /* XXX technically not correct, could be udptl too */
|
|
|
|
|
|
|
|
|
|
|
|
__rtp_stats_update(a->rtp_stats, &A->codecs);
|
|
|
|
__rtp_stats_update(a->rtp_stats, &A->codecs);
|
|
|
|
@ -1433,7 +1434,7 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE))
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE))
|
|
|
|
{ /* RTCP sink handler added below */ }
|
|
|
|
{ /* RTCP sink handler added below */ }
|
|
|
|
else if (b)
|
|
|
|
else if (b)
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, b);
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, b, rtcp_only);
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
PS_CLEAR(a, IMPLICIT_RTCP);
|
|
|
|
PS_CLEAR(a, IMPLICIT_RTCP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1447,12 +1448,12 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru
|
|
|
|
a = la->data;
|
|
|
|
a = la->data;
|
|
|
|
|
|
|
|
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) {
|
|
|
|
if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) {
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, a);
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, a, rtcp_only);
|
|
|
|
if (MEDIA_ISSET(A, RTCP_MUX))
|
|
|
|
if (MEDIA_ISSET(A, RTCP_MUX))
|
|
|
|
__add_sink_handler(&ax->rtcp_sinks, a);
|
|
|
|
__add_sink_handler(&ax->rtcp_sinks, a, rtcp_only);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (b)
|
|
|
|
else if (b)
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, b);
|
|
|
|
__add_sink_handler(&a->rtcp_sinks, b, rtcp_only);
|
|
|
|
PS_CLEAR(a, RTP);
|
|
|
|
PS_CLEAR(a, RTP);
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
PS_SET(a, RTCP);
|
|
|
|
a->rtcp_sibling = NULL;
|
|
|
|
a->rtcp_sibling = NULL;
|
|
|
|
@ -2484,6 +2485,7 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams
|
|
|
|
|
|
|
|
|
|
|
|
// create media iterators for all subscribers
|
|
|
|
// create media iterators for all subscribers
|
|
|
|
GList *sub_medias[ml->subscribers.length];
|
|
|
|
GList *sub_medias[ml->subscribers.length];
|
|
|
|
|
|
|
|
bool subs_rtcp_only[ml->subscribers.length];
|
|
|
|
unsigned int num_subs = 0;
|
|
|
|
unsigned int num_subs = 0;
|
|
|
|
for (GList *l = ml->subscribers.head; l; l = l->next) {
|
|
|
|
for (GList *l = ml->subscribers.head; l; l = l->next) {
|
|
|
|
struct call_subscription *cs = l->data;
|
|
|
|
struct call_subscription *cs = l->data;
|
|
|
|
@ -2492,6 +2494,7 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams
|
|
|
|
// skip into correct media section for multi-ml subscriptions
|
|
|
|
// skip into correct media section for multi-ml subscriptions
|
|
|
|
for (unsigned int offset = cs->media_offset; offset && sub_medias[num_subs]; offset--)
|
|
|
|
for (unsigned int offset = cs->media_offset; offset && sub_medias[num_subs]; offset--)
|
|
|
|
sub_medias[num_subs] = sub_medias[num_subs]->next;
|
|
|
|
sub_medias[num_subs] = sub_medias[num_subs]->next;
|
|
|
|
|
|
|
|
subs_rtcp_only[num_subs] = cs->rtcp_only ? true : false;
|
|
|
|
num_subs++;
|
|
|
|
num_subs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// keep num_subs as shortcut to ml->subscribers.length
|
|
|
|
// keep num_subs as shortcut to ml->subscribers.length
|
|
|
|
@ -2517,8 +2520,9 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams
|
|
|
|
|
|
|
|
|
|
|
|
struct call_media *sub_media = sub_medias[i]->data;
|
|
|
|
struct call_media *sub_media = sub_medias[i]->data;
|
|
|
|
sub_medias[i] = sub_medias[i]->next;
|
|
|
|
sub_medias[i] = sub_medias[i]->next;
|
|
|
|
|
|
|
|
bool rtcp_only = subs_rtcp_only[i];
|
|
|
|
|
|
|
|
|
|
|
|
if (__init_streams(media, sub_media, sp, flags))
|
|
|
|
if (__init_streams(media, sub_media, sp, flags, rtcp_only))
|
|
|
|
ilog(LOG_WARN, "Error initialising streams");
|
|
|
|
ilog(LOG_WARN, "Error initialising streams");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -2939,7 +2943,7 @@ static void __unsubscribe_from_all(struct call_monologue *ml) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void __add_subscription(struct call_monologue *which, struct call_monologue *to, bool offer_answer,
|
|
|
|
void __add_subscription(struct call_monologue *which, struct call_monologue *to, bool offer_answer,
|
|
|
|
unsigned int offset)
|
|
|
|
unsigned int offset, bool rtcp_only)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (g_hash_table_lookup(which->subscriptions_ht, to)) {
|
|
|
|
if (g_hash_table_lookup(which->subscriptions_ht, to)) {
|
|
|
|
ilog(LOG_DEBUG, "Tag '" STR_FORMAT_M "' is already subscribed to '" STR_FORMAT_M "'",
|
|
|
|
ilog(LOG_DEBUG, "Tag '" STR_FORMAT_M "' is already subscribed to '" STR_FORMAT_M "'",
|
|
|
|
@ -2956,6 +2960,8 @@ void __add_subscription(struct call_monologue *which, struct call_monologue *to,
|
|
|
|
to_rev_cs->monologue = which;
|
|
|
|
to_rev_cs->monologue = which;
|
|
|
|
which_cs->media_offset = offset;
|
|
|
|
which_cs->media_offset = offset;
|
|
|
|
to_rev_cs->media_offset = offset;
|
|
|
|
to_rev_cs->media_offset = offset;
|
|
|
|
|
|
|
|
which_cs->rtcp_only = rtcp_only ? 1 : 0;
|
|
|
|
|
|
|
|
to_rev_cs->rtcp_only = rtcp_only ? 1 : 0;
|
|
|
|
// keep offer-answer subscriptions first in the list
|
|
|
|
// keep offer-answer subscriptions first in the list
|
|
|
|
if (!offer_answer) {
|
|
|
|
if (!offer_answer) {
|
|
|
|
g_queue_push_tail(&which->subscriptions, which_cs);
|
|
|
|
g_queue_push_tail(&which->subscriptions, which_cs);
|
|
|
|
@ -2977,8 +2983,8 @@ void __add_subscription(struct call_monologue *which, struct call_monologue *to,
|
|
|
|
static void __subscribe_offer_answer_both_ways(struct call_monologue *a, struct call_monologue *b) {
|
|
|
|
static void __subscribe_offer_answer_both_ways(struct call_monologue *a, struct call_monologue *b) {
|
|
|
|
__unsubscribe_all_offer_answer_subscribers(a);
|
|
|
|
__unsubscribe_all_offer_answer_subscribers(a);
|
|
|
|
__unsubscribe_all_offer_answer_subscribers(b);
|
|
|
|
__unsubscribe_all_offer_answer_subscribers(b);
|
|
|
|
__add_subscription(a, b, true, 0);
|
|
|
|
__add_subscription(a, b, true, 0, false);
|
|
|
|
__add_subscription(b, a, true, 0);
|
|
|
|
__add_subscription(b, a, true, 0, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -3037,7 +3043,7 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_
|
|
|
|
__assign_stream_fds(media, &em->intf_sfds);
|
|
|
|
__assign_stream_fds(media, &em->intf_sfds);
|
|
|
|
|
|
|
|
|
|
|
|
// XXX this should be covered by __update_init_subscribers ?
|
|
|
|
// XXX this should be covered by __update_init_subscribers ?
|
|
|
|
if (__init_streams(media, NULL, sp, flags))
|
|
|
|
if (__init_streams(media, NULL, sp, flags, false))
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
__ice_start(media);
|
|
|
|
__ice_start(media);
|
|
|
|
ice_update(media->ice_agent, sp, false);
|
|
|
|
ice_update(media->ice_agent, sp, false);
|
|
|
|
@ -3050,7 +3056,7 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_
|
|
|
|
static int monologue_subscribe_request1(struct call_monologue *src_ml, struct call_monologue *dst_ml,
|
|
|
|
static int monologue_subscribe_request1(struct call_monologue *src_ml, struct call_monologue *dst_ml,
|
|
|
|
struct sdp_ng_flags *flags, GList **src_media_it, GList **dst_media_it, unsigned int *index)
|
|
|
|
struct sdp_ng_flags *flags, GList **src_media_it, GList **dst_media_it, unsigned int *index)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
unsigned int idx_diff = 0;
|
|
|
|
unsigned int idx_diff = 0, rev_idx_diff = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (GList *l = src_ml->last_in_sdp_streams.head; l; l = l->next) {
|
|
|
|
for (GList *l = src_ml->last_in_sdp_streams.head; l; l = l->next) {
|
|
|
|
struct stream_params *sp = l->data;
|
|
|
|
struct stream_params *sp = l->data;
|
|
|
|
@ -3061,6 +3067,8 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca
|
|
|
|
// track media index difference if one ml is subscribed to multiple other mls
|
|
|
|
// track media index difference if one ml is subscribed to multiple other mls
|
|
|
|
if (idx_diff == 0 && dst_media->index > src_media->index)
|
|
|
|
if (idx_diff == 0 && dst_media->index > src_media->index)
|
|
|
|
idx_diff = dst_media->index - src_media->index;
|
|
|
|
idx_diff = dst_media->index - src_media->index;
|
|
|
|
|
|
|
|
if (rev_idx_diff == 0 && src_media->index > dst_media->index)
|
|
|
|
|
|
|
|
rev_idx_diff = src_media->index - dst_media->index;
|
|
|
|
|
|
|
|
|
|
|
|
if (__media_init_from_flags(src_media, dst_media, sp, flags) == 1)
|
|
|
|
if (__media_init_from_flags(src_media, dst_media, sp, flags) == 1)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
@ -3100,11 +3108,13 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca
|
|
|
|
__num_media_streams(dst_media, num_ports);
|
|
|
|
__num_media_streams(dst_media, num_ports);
|
|
|
|
__assign_stream_fds(dst_media, &em->intf_sfds);
|
|
|
|
__assign_stream_fds(dst_media, &em->intf_sfds);
|
|
|
|
|
|
|
|
|
|
|
|
if (__init_streams(dst_media, NULL, NULL, flags))
|
|
|
|
if (__init_streams(dst_media, NULL, NULL, flags, false))
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
__add_subscription(dst_ml, src_ml, false, idx_diff);
|
|
|
|
__add_subscription(dst_ml, src_ml, false, idx_diff, false);
|
|
|
|
|
|
|
|
if (flags->rtcp_mirror)
|
|
|
|
|
|
|
|
__add_subscription(src_ml, dst_ml, false, rev_idx_diff, true);
|
|
|
|
|
|
|
|
|
|
|
|
__update_init_subscribers(src_ml, NULL, NULL, flags->opmode);
|
|
|
|
__update_init_subscribers(src_ml, NULL, NULL, flags->opmode);
|
|
|
|
__update_init_subscribers(dst_ml, NULL, NULL, flags->opmode);
|
|
|
|
__update_init_subscribers(dst_ml, NULL, NULL, flags->opmode);
|
|
|
|
@ -3180,7 +3190,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, struct sdp_ng_flag
|
|
|
|
|
|
|
|
|
|
|
|
__dtls_logic(flags, dst_media, sp);
|
|
|
|
__dtls_logic(flags, dst_media, sp);
|
|
|
|
|
|
|
|
|
|
|
|
if (__init_streams(dst_media, NULL, sp, flags))
|
|
|
|
if (__init_streams(dst_media, NULL, sp, flags, false))
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
MEDIA_CLEAR(dst_media, RECV);
|
|
|
|
MEDIA_CLEAR(dst_media, RECV);
|
|
|
|
|