📄 soa_static.c
字号:
return common_codecs; /* Select unique dynamic payload type for each payload */ memset(dynamic_pt, 0, sizeof dynamic_pt); for (lrm = l_m->m_rtpmaps; lrm; lrm = lrm->rm_next) { if (!lrm->rm_any) dynamic_pt[lrm->rm_pt] = 1; } for (rrm = r_m->m_rtpmaps; rrm; rrm = rrm->rm_next) { dynamic_pt[rrm->rm_pt] = 1; } for (next_lrm = &l_m->m_rtpmaps; (lrm = *next_lrm); ) { if (!lrm->rm_any) { next_lrm = &lrm->rm_next; continue; } lrm->rm_any = 0; pt = lrm->rm_pt; if (dynamic_pt[pt]) { for (pt = 96; pt < 128; pt++) if (!dynamic_pt[pt]) break; if (pt == 128) { for (pt = 0; pt < 128; pt++) if (!sdp_rtpmap_well_known[pt] && !dynamic_pt[pt]) break; } if (pt == 128) { for (pt = 0; pt < 128; pt++) if (!dynamic_pt[pt]) break; } if (pt == 128) { /* Too many payload types */ *next_lrm = lrm->rm_next; continue; } lrm->rm_pt = pt; lrm->rm_predef = 0; } dynamic_pt[pt] = 1; next_lrm = &lrm->rm_next; } return common_codecs;}/** Sort rtpmaps in @a inout_list according to the values in @a rrm. * * @return Number of common codecs */staticint soa_sdp_sort_rtpmap(sdp_rtpmap_t **inout_list, sdp_rtpmap_t const *rrm, char const *auxiliary){ sdp_rtpmap_t *sorted = NULL, **next = &sorted, **left; sdp_rtpmap_t *aux = NULL, **next_aux = &aux; int common_codecs = 0; assert(inout_list); if (!inout_list) return 0; /* If remote has only single codec, ignore list of auxiliary codecs */ if (rrm && !rrm->rm_next) auxiliary = NULL; /* Insertion sort from *inout_list to sorted */ for (; rrm && *inout_list; rrm = rrm->rm_next) { for (left = inout_list; *left; left = &(*left)->rm_next) { if (sdp_rtpmap_match(rrm, (*left))) break; } if (!*left) continue; if (auxiliary && soa_sdp_is_auxiliary_codec(rrm, auxiliary)) { *next_aux = *left, next_aux = &(*next_aux)->rm_next; } else { common_codecs++; *next = *left; next = &(*next)->rm_next; } *left = (*left)->rm_next; } /* Append common auxiliary codecs */ if (aux) *next = aux, next = next_aux; /* Append leftover codecs */ *next = *inout_list; *inout_list = sorted; return common_codecs;}/** Select rtpmaps in @a inout_list according to the values in @a rrm. * * @return Number of common codecs */staticint soa_sdp_select_rtpmap(sdp_rtpmap_t **inout_list, sdp_rtpmap_t const *rrm, char const *auxiliary, int select_single){ sdp_rtpmap_t **left; sdp_rtpmap_t *aux = NULL, **next_aux = &aux; int common_codecs = 0; assert(inout_list); if (!inout_list) return 0; for (left = inout_list; *left; ) { if (auxiliary && soa_sdp_is_auxiliary_codec(*left, auxiliary)) /* Insert into list of auxiliary codecs */ *next_aux = *left, *left = (*left)->rm_next, next_aux = &(*next_aux)->rm_next; else if (!(select_single && common_codecs > 0) && sdp_rtpmap_find_matching(rrm, (*left))) /* Select */ left = &(*left)->rm_next, common_codecs++; else /* Remove */ *left = (*left)->rm_next; } *left = aux, *next_aux = NULL; return common_codecs;}/** Sort and select rtpmaps */ staticint soa_sdp_media_upgrade_rtpmaps(soa_session_t *ss, sdp_media_t *sm, sdp_media_t const *rm){ soa_static_session_t *sss = (soa_static_session_t *)ss; char const *auxiliary = NULL; int common_codecs; common_codecs = soa_sdp_set_rtpmap_pt(sm, rm); if (rm->m_type == sdp_media_audio) auxiliary = sss->sss_audio_aux; if (ss->ss_rtp_sort == SOA_RTP_SORT_REMOTE || (ss->ss_rtp_sort == SOA_RTP_SORT_DEFAULT && rm->m_mode == sdp_recvonly)) { soa_sdp_sort_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary); } if (common_codecs == 0) ; else if (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE) { soa_sdp_select_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary, 1); } else if (ss->ss_rtp_select == SOA_RTP_SELECT_COMMON) { soa_sdp_select_rtpmap(&sm->m_rtpmaps, rm->m_rtpmaps, auxiliary, 0); } return common_codecs;}/** Sort and select rtpmaps within session */ staticint soa_sdp_session_upgrade_rtpmaps(soa_session_t *ss, sdp_session_t *session, sdp_session_t const *remote){ sdp_media_t *sm; sdp_media_t const *rm; for (sm = session->sdp_media, rm = remote->sdp_media; sm && rm; sm = sm->m_next, rm = rm->m_next) { if (!sm->m_rejected && sdp_media_uses_rtp(sm)) soa_sdp_media_upgrade_rtpmaps(ss, sm, rm); } return 0;}/** Upgrade m= lines within session */ staticint soa_sdp_upgrade(soa_session_t *ss, su_home_t *home, sdp_session_t *session, sdp_session_t const *user, sdp_session_t const *remote, int **return_u2s, int **return_s2u){ soa_static_session_t *sss = (soa_static_session_t *)ss; int Ns, Nu, Nr, size, i, j; sdp_media_t *m, **mm, *um; sdp_media_t **s_media, **o_media, **u_media; sdp_media_t const *rm, **r_media; int *u2s = NULL, *s2u = NULL; if (session == NULL || user == NULL) return (errno = EFAULT), -1; Ns = sdp_media_count(session, sdp_media_any, 0, 0, 0); Nu = sdp_media_count(user, sdp_media_any, 0, 0, 0); Nr = sdp_media_count(remote, sdp_media_any, 0, 0, 0); if (remote == NULL) size = Ns + Nu + 1; else if (Ns < Nr) size = Nr + 1; else size = Ns + 1; s_media = su_zalloc(home, size * (sizeof *s_media)); o_media = su_zalloc(home, (Ns + 1) * (sizeof *o_media)); u_media = su_zalloc(home, (Nu + 1) * (sizeof *u_media)); r_media = su_zalloc(home, (Nr + 1) * (sizeof *r_media)); if (!s_media || !o_media || !u_media || !r_media) return -1; um = sdp_media_dup_all(home, user->sdp_media, session); if (!um && user->sdp_media) return -1; u2s = su_alloc(home, (Nu + 1) * sizeof(*u2s)); s2u = su_alloc(home, size * sizeof(*s2u)); if (!u2s || !s2u) return -1; for (i = 0; i < Nu; i++) u2s[i] = U2S_NOT_USED; u2s[i] = U2S_SENTINEL; for (i = 0; i <= size; i++) s2u[i] = U2S_NOT_USED; s2u[i] = U2S_SENTINEL; for (i = 0, m = session->sdp_media; m && i < Ns; m = m->m_next) o_media[i++] = m; assert(i == Ns); for (i = 0, m = um; m && i < Nu; m = m->m_next) u_media[i++] = m; assert(i == Nu); m = remote ? remote->sdp_media : NULL; for (i = 0; m && i < Nr; m = m->m_next) r_media[i++] = m; assert(i == Nr); if (sss->sss_ordered_user && sss->sss_u2s) { /* User SDP is ordered */ for (j = 0; sss->sss_u2s[j] != U2S_SENTINEL; j++) { i = sss->sss_u2s[j]; if (i == U2S_NOT_USED) continue; if (j >= Nu) /* lines removed from user SDP */ continue; s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE; u2s[j] = i, s2u[i] = j; } } if (remote) { /* Update session according to remote */ for (i = 0; i < Nr; i++) { rm = r_media[i]; m = s_media[i]; if (!m) { int codec_mismatch = 0; if (!rm->m_rejected) j = soa_sdp_matching_mindex(ss, u_media, rm, &codec_mismatch); else j = -1; if (j == -1) { s_media[i] = soa_sdp_make_rejected_media(home, rm, session, 0); continue; } else if (codec_mismatch && !ss->ss_rtp_mismatch) { m = soa_sdp_make_rejected_media(home, u_media[j], session, 1); soa_sdp_set_rtpmap_pt(s_media[i] = m, rm); continue; } s_media[i] = m = u_media[j]; u_media[j] = SDP_MEDIA_NONE; u2s[j] = i, s2u[i] = j; } if (sdp_media_uses_rtp(rm)) soa_sdp_media_upgrade_rtpmaps(ss, m, rm); } } else { if (sss->sss_ordered_user) { /* Update session with unused media in u_media */ if (!sss->sss_reuse_rejected) { /* Mark previously used slots */ for (i = 0; i < Ns; i++) { if (s_media[i]) continue; s_media[i] = soa_sdp_make_rejected_media(home, o_media[i], session, 0); } } for (j = 0; j < Nu; j++) { if (u_media[j] == SDP_MEDIA_NONE) continue; for (i = 0; i < size - 1; i++) { if (s_media[i] == NULL) { s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE; u2s[j] = i, s2u[i] = j; break; } } assert(i != size - 1); } } /* Match unused user media by media types with the existing session */ for (i = 0; i < Ns; i++) { if (s_media[i]) continue; j = soa_sdp_matching_mindex(ss, u_media, o_media[i], NULL); if (j == -1) { s_media[i] = soa_sdp_make_rejected_media(home, o_media[i], session, 0); continue; } s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE; u2s[j] = i, s2u[i] = j; } /* Here we just append new media at the end */ for (j = 0; j < Nu; j++) { if (u_media[j] != SDP_MEDIA_NONE) { s_media[i] = u_media[j], u_media[j] = SDP_MEDIA_NONE; u2s[j] = i, s2u[i] = j; i++; } } assert(i <= size); } mm = &session->sdp_media; for (i = 0; s_media[i]; i++) { m = s_media[i]; *mm = m; mm = &m->m_next; } *mm = NULL; s2u[size = i] = U2S_SENTINEL; *return_u2s = u2s; *return_s2u = s2u;#ifndef NDEBUG /* X check */ for (j = 0; j < Nu; j++) { i = u2s[j]; assert(i == U2S_NOT_USED || s2u[i] == j); } for (i = 0; i < size; i++) { j = s2u[i]; assert(j == U2S_NOT_USED || u2s[j] == i); }#endif return 0;}int *u2s_alloc(su_home_t *home, int const *u2s){ if (u2s) { int i, *a; for (i = 0; u2s[i] != U2S_SENTINEL; i++) ; a = su_alloc(home, (i + 1) * (sizeof *u2s)); if (a) memcpy(a, u2s, (i + 1) * (sizeof *u2s)); return a; } return NULL;}/** Check if @a session contains media that are rejected by @a remote. */ staticint soa_sdp_reject_is_needed(sdp_session_t const *session, sdp_session_t const *remote){ sdp_media_t const *sm, *rm; if (!remote) return 1; if (!session) return 0; for (sm = session->sdp_media, rm = remote->sdp_media; sm && rm; sm = sm->m_next, rm = rm->m_next) { if (rm->m_rejected) { if (!sm->m_rejected) return 1; } else { /* Mode bits do not match */ if (((rm->m_mode & sdp_recvonly) == sdp_recvonly) != ((sm->m_mode & sdp_sendonly) == sdp_sendonly)) return 1; } } if (sm) return 1; return 0;}/** If m= line is rejected by remote mark m= line rejected within session */ staticint soa_sdp_reject(su_home_t *home, sdp_session_t *session, sdp_session_t const *remote){ sdp_media_t *sm; sdp_media_t const *rm; if (!session || !session->sdp_media || !remote) return 0; rm = remote->sdp_media; for (sm = session->sdp_media; sm; sm = sm->m_next) { if (!rm || rm->m_rejected) { sm->m_rejected = 1; sm->m_mode = 0; sm->m_port = 0; sm->m_number_of_ports = 1; if (sm->m_format) sm->m_format->l_next = NULL; if (sm->m_rtpmaps) sm->m_rtpmaps->rm_next = NULL; sm->m_information = NULL; if (sm->m_connections) sm->m_connections->c_next = NULL; sm->m_bandwidths = NULL; sm->m_key = NULL; sm->m_attributes = NULL; sm->m_user = NULL; } if (rm) rm = rm->m_next; } return 0;}/** Update mode within session. * * @sa soatag_hold
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -