diff --git a/daemon/call.c b/daemon/call.c index df79f8bee..7606b79da 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2372,121 +2372,132 @@ static struct call_subscription *find_subscription(struct call_monologue *ml, st return call_get_call_subscription(ml->subscribers_ht, sub); } -void codecs_offer_answer(struct call_media *media, struct call_media *other_media, + +__attribute__((nonnull(1, 2, 3, 5))) +static void codecs_offer(struct call_media *media, struct call_media *other_media, struct stream_params *sp, struct sdp_ng_flags *flags, struct call_subscription *dialogue[2]) { - if (!flags || flags->opmode != OP_ANSWER) { - // offer - ilogs(codec, LOG_DEBUG, "Updating codecs for offerer " STR_FORMAT " #%u", - STR_FMT(&other_media->monologue->tag), - other_media->index); - if (flags) { - if (flags->reuse_codec) - codec_store_populate_reuse(&other_media->codecs, &sp->codecs, - .codec_set = flags->codec_set); - else - codec_store_populate(&other_media->codecs, &sp->codecs, - .codec_set = flags->codec_set); - codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); - codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); - if (!other_media->codecs.strip_full) - codec_store_offer(&other_media->codecs, &flags->codec_transcode, &sp->codecs); - codec_store_check_empty(&other_media->codecs, &sp->codecs); - codec_store_accept(&other_media->codecs, &flags->codec_accept, NULL); - codec_store_accept(&other_media->codecs, &flags->codec_consume, &sp->codecs); - codec_store_track(&other_media->codecs, &flags->codec_mask); - } else - codec_store_populate(&other_media->codecs, &sp->codecs); - - // we don't update the answerer side if the offer is not RTP but is going - // to RTP (i.e. T.38 transcoding) - instead we leave the existing codec list - // intact - bool update_answerer = true; - if (proto_is_rtp(media->protocol) && !proto_is_rtp(other_media->protocol)) - update_answerer = false; - - if (update_answerer) { - // update/create answer/receiver side - ilogs(codec, LOG_DEBUG, "Updating codecs for answerer " STR_FORMAT " #%u", - STR_FMT(&media->monologue->tag), - media->index); - if (flags && flags->reuse_codec) - codec_store_populate_reuse(&media->codecs, &sp->codecs); - else - codec_store_populate(&media->codecs, &sp->codecs); - } - if (flags) { - codec_store_strip(&media->codecs, &flags->codec_strip, flags->codec_except); - codec_store_strip(&media->codecs, &flags->codec_consume, flags->codec_except); - codec_store_strip(&media->codecs, &flags->codec_mask, flags->codec_except); - codec_store_offer(&media->codecs, &flags->codec_offer, &sp->codecs); - codec_store_transcode(&media->codecs, &flags->codec_transcode, &sp->codecs); - codec_store_check_empty(&media->codecs, &sp->codecs); - } - codec_store_synthesise(&media->codecs, &other_media->codecs); - - // update supp codecs based on actions so far - codec_tracker_update(&media->codecs); - - // set up handlers - codec_handlers_update(media, other_media, .flags = flags, .sp = sp); - - // updating the handlers may have removed some codecs, so run update the supp codecs again - codec_tracker_update(&media->codecs); - - // finally set up handlers again based on final results - codec_handlers_update(media, other_media, .flags = flags, .sp = sp, .sub = dialogue[1]); - } - else { - // answer - ilogs(codec, LOG_DEBUG, "Updating codecs for answerer " STR_FORMAT " #%u", - STR_FMT(&other_media->monologue->tag), - other_media->index); - - bool codec_answer_only = true; - // don't do codec answer for a rejected media section - if (other_media->streams.length == 0) - codec_answer_only = false; - else if (sp->rtp_endpoint.port == 0) - codec_answer_only = false; - + ilogs(codec, LOG_DEBUG, "Updating codecs for offerer " STR_FORMAT " #%u", + STR_FMT(&other_media->monologue->tag), + other_media->index); + if (flags) { if (flags->reuse_codec) codec_store_populate_reuse(&other_media->codecs, &sp->codecs, - .codec_set = flags->codec_set, - .answer_only = codec_answer_only); + .codec_set = flags->codec_set); else codec_store_populate(&other_media->codecs, &sp->codecs, - .codec_set = flags->codec_set, - .answer_only = codec_answer_only); + .codec_set = flags->codec_set); codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); + if (!other_media->codecs.strip_full) + codec_store_offer(&other_media->codecs, &flags->codec_transcode, &sp->codecs); codec_store_check_empty(&other_media->codecs, &sp->codecs); + codec_store_accept(&other_media->codecs, &flags->codec_accept, NULL); + codec_store_accept(&other_media->codecs, &flags->codec_consume, &sp->codecs); + codec_store_track(&other_media->codecs, &flags->codec_mask); + } else + codec_store_populate(&other_media->codecs, &sp->codecs); + + // we don't update the answerer side if the offer is not RTP but is going + // to RTP (i.e. T.38 transcoding) - instead we leave the existing codec list + // intact + bool update_answerer = true; + if (proto_is_rtp(media->protocol) && !proto_is_rtp(other_media->protocol)) + update_answerer = false; + + if (update_answerer) { + // update/create answer/receiver side + ilogs(codec, LOG_DEBUG, "Updating codecs for answerer " STR_FORMAT " #%u", + STR_FMT(&media->monologue->tag), + media->index); + if (flags && flags->reuse_codec) + codec_store_populate_reuse(&media->codecs, &sp->codecs); + else + codec_store_populate(&media->codecs, &sp->codecs); + } + if (flags) { + codec_store_strip(&media->codecs, &flags->codec_strip, flags->codec_except); + codec_store_strip(&media->codecs, &flags->codec_consume, flags->codec_except); + codec_store_strip(&media->codecs, &flags->codec_mask, flags->codec_except); + codec_store_offer(&media->codecs, &flags->codec_offer, &sp->codecs); + codec_store_transcode(&media->codecs, &flags->codec_transcode, &sp->codecs); + codec_store_check_empty(&media->codecs, &sp->codecs); + } + codec_store_synthesise(&media->codecs, &other_media->codecs); - // update callee side codec handlers again (second pass after the offer) as we - // might need to update some handlers, e.g. when supplemental codecs have been - // rejected - codec_handlers_update(other_media, media); + // update supp codecs based on actions so far + codec_tracker_update(&media->codecs); - // finally set up our caller side codecs - ilogs(codec, LOG_DEBUG, "Codec answer for " STR_FORMAT " #%u", - STR_FMT(&other_media->monologue->tag), - other_media->index); - codec_store_answer(&media->codecs, &other_media->codecs, flags); + // set up handlers + codec_handlers_update(media, other_media, .flags = flags, .sp = sp); - // set up handlers - codec_handlers_update(media, other_media, .flags = flags, .sp = sp); + // updating the handlers may have removed some codecs, so run update the supp codecs again + codec_tracker_update(&media->codecs); - // updating the handlers may have removed some codecs, so run update the supp codecs again - codec_tracker_update(&media->codecs); - codec_tracker_update(&other_media->codecs); + // finally set up handlers again based on final results + codec_handlers_update(media, other_media, .flags = flags, .sp = sp, .sub = dialogue[1]); +} - // finally set up handlers again based on final results - codec_handlers_update(media, other_media, .flags = flags, .sp = sp, .sub = dialogue[1]); - codec_handlers_update(other_media, media, .sub = dialogue[0]); +__attribute__((nonnull(1, 2, 3, 4, 5))) +static void codecs_answer(struct call_media *media, struct call_media *other_media, + struct stream_params *sp, struct sdp_ng_flags *flags, struct call_subscription *dialogue[2]) +{ + ilogs(codec, LOG_DEBUG, "Updating codecs for answerer " STR_FORMAT " #%u", + STR_FMT(&other_media->monologue->tag), + other_media->index); + + bool codec_answer_only = true; + // don't do codec answer for a rejected media section + if (other_media->streams.length == 0) + codec_answer_only = false; + else if (sp->rtp_endpoint.port == 0) + codec_answer_only = false; + + if (flags->reuse_codec) + codec_store_populate_reuse(&other_media->codecs, &sp->codecs, + .codec_set = flags->codec_set, + .answer_only = codec_answer_only); + else + codec_store_populate(&other_media->codecs, &sp->codecs, + .codec_set = flags->codec_set, + .answer_only = codec_answer_only); + codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); + codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); + codec_store_check_empty(&other_media->codecs, &sp->codecs); + + // update callee side codec handlers again (second pass after the offer) as we + // might need to update some handlers, e.g. when supplemental codecs have been + // rejected + codec_handlers_update(other_media, media); + + // finally set up our caller side codecs + ilogs(codec, LOG_DEBUG, "Codec answer for " STR_FORMAT " #%u", + STR_FMT(&other_media->monologue->tag), + other_media->index); + codec_store_answer(&media->codecs, &other_media->codecs, flags); + + // set up handlers + codec_handlers_update(media, other_media, .flags = flags, .sp = sp); + + // updating the handlers may have removed some codecs, so run update the supp codecs again + codec_tracker_update(&media->codecs); + codec_tracker_update(&other_media->codecs); + + // finally set up handlers again based on final results + codec_handlers_update(media, other_media, .flags = flags, .sp = sp, .sub = dialogue[1]); + codec_handlers_update(other_media, media, .sub = dialogue[0]); + + // activate audio player if needed (not done by codec_handlers_update without `flags`) + audio_player_activate(media); +} - // activate audio player if needed (not done by codec_handlers_update without `flags`) - audio_player_activate(media); - } +void codecs_offer_answer(struct call_media *media, struct call_media *other_media, + struct stream_params *sp, struct sdp_ng_flags *flags, struct call_subscription *dialogue[2]) +{ + if (!flags || flags->opmode != OP_ANSWER) + codecs_offer(media, other_media, sp, flags, dialogue); + else + codecs_answer(media, other_media, sp, flags, dialogue); } diff --git a/include/call.h b/include/call.h index 63b7ce7ae..3f7d870e6 100644 --- a/include/call.h +++ b/include/call.h @@ -727,6 +727,7 @@ struct call_monologue *call_get_monologue(struct call *call, const str *fromtag) struct call_monologue *call_get_or_create_monologue(struct call *call, const str *fromtag); struct call *call_get(const str *callid); int monologue_offer_answer(struct call_subscription *dialogue[2], GQueue *streams, struct sdp_ng_flags *flags); +__attribute__((nonnull(1, 2, 3, 5))) void codecs_offer_answer(struct call_media *media, struct call_media *other_media, struct stream_params *sp, struct sdp_ng_flags *flags, struct call_subscription *dialogue[2]); int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_flags *flags);