📄 sdp.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/ietf.h>#include <gpac/token.h>#define SDP_WRITE_STEPALLOC 2048GF_EXPORTGF_SDP_FMTP *gf_sdp_fmtp_new(){ GF_SDP_FMTP *tmp = (GF_SDP_FMTP*)malloc(sizeof(GF_SDP_FMTP)); tmp->PayloadType = 0; tmp->Attributes = gf_list_new(); return tmp;}GF_EXPORTvoid gf_sdp_fmtp_del(GF_SDP_FMTP *fmtp){ GF_X_Attribute *att; if (!fmtp) return; while (gf_list_count(fmtp->Attributes)) { att = (GF_X_Attribute*)gf_list_get(fmtp->Attributes, 0); gf_list_rem(fmtp->Attributes, 0); if (att->Name) free(att->Name); if (att->Value) free(att->Value); free(att); } gf_list_del(fmtp->Attributes); free(fmtp);}GF_SDP_FMTP *SDP_GetFMTPForPayload(GF_SDPMedia *media, u32 PayloadType){ GF_SDP_FMTP *tmp; u32 i; if (!media) return NULL; i=0; while ((tmp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) { if (tmp->PayloadType == PayloadType) return tmp; } return NULL;}void SDP_ParseAttribute(GF_SDPInfo *sdp, char *buffer, GF_SDPMedia *media){ s32 pos; u32 PayT; char comp[3000]; GF_RTPMap *map; GF_SDP_FMTP *fmtp; GF_X_Attribute *att; pos = gf_token_get(buffer, 0, " :\t\r\n", comp, 3000); if (!strcmp(comp, "cat")) { if (media) return; pos = gf_token_get(buffer, pos, ":\t\r\n", comp, 3000); sdp->a_cat = strdup(comp); return; } if (!strcmp(comp, "keywds")) { if (media) return; pos = gf_token_get(buffer, pos, ":\t\r\n", comp, 3000); sdp->a_keywds = strdup(comp); return; } if (!strcmp(comp, "tool")) { if (media) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); sdp->a_tool = strdup(comp); return; } if (!strcmp(comp, "ptime")) { if (!media) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); media->PacketTime = atoi(comp); return; } if (!strcmp(comp, "recvonly")) { if (!media) { sdp->a_SendRecieve = 1; } else { media->SendRecieve = 1; } return; } if (!strcmp(comp, "sendonly")) { if (!media) { sdp->a_SendRecieve = 2; } else { media->SendRecieve = 2; } return; } if (!strcmp(comp, "sendrecv")) { if (!media) { sdp->a_SendRecieve = 3; } else { media->SendRecieve = 3; } return; } if (!strcmp(comp, "orient")) { if (!media || media->Type) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); media->orientation = strdup(comp); return; } if (!strcmp(comp, "type")) { if (media) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); sdp->a_type = strdup(comp); return; } if (!strcmp(comp, "charset")) { if (media) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); sdp->a_charset = strdup(comp); return; } if (!strcmp(comp, "sdplang")) { pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); if (media) { media->sdplang = strdup(comp); } else { sdp->a_sdplang = strdup(comp); } return; } if (!strcmp(comp, "lang")) { pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); if (media) { media->lang = strdup(comp); } else { sdp->a_lang = strdup(comp); } return; } if (!strcmp(comp, "framerate")) { //only for video if (!media || (media->Type != 1)) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); media->FrameRate = atof(comp); return; } if (!strcmp(comp, "quality")) { if (!media) return; pos = gf_token_get(buffer, pos, ":\r\n", comp, 3000); media->Quality = atoi(comp); return; } if (!strcmp(comp, "rtpmap")) { if (!media) return; map = (GF_RTPMap*)malloc(sizeof(GF_RTPMap)); pos = gf_token_get(buffer, pos, ": \r\n", comp, 3000); map->PayloadType = atoi(comp); pos = gf_token_get(buffer, pos, " /\r\n", comp, 3000); map->payload_name = strdup(comp); pos = gf_token_get(buffer, pos, " /\r\n", comp, 3000); map->ClockRate = atoi(comp); pos = gf_token_get(buffer, pos, " /\r\n", comp, 3000); map->AudioChannels = (pos > 0) ? atoi(comp) : 0; gf_list_add(media->RTPMaps, map); return; } //FMTP if (!strcmp(comp, "fmtp")) { if (!media) return; pos = gf_token_get(buffer, pos, ": \r\n", comp, 3000); PayT = atoi(comp); fmtp = SDP_GetFMTPForPayload(media, PayT); if (!fmtp) { fmtp = gf_sdp_fmtp_new(); fmtp->PayloadType = PayT; gf_list_add(media->FMTP, fmtp); } while (1) { pos = gf_token_get(buffer, pos, "; =\r\n", comp, 3000); if (pos <= 0) break; att = (GF_X_Attribute*)malloc(sizeof(GF_X_Attribute)); att->Name = strdup(comp); att->Value = NULL; pos ++; pos = gf_token_get(buffer, pos, ";\r\n", comp, 3000); if (pos > 0) att->Value = strdup(comp); gf_list_add(fmtp->Attributes, att); } return; } //the rest cannot be discarded that way as it may be application-specific //so keep it. //a= <attribute> || <attribute>:<value> //we add <attribute> <value> in case ... pos = gf_token_get(buffer, 0, " :\r\n", comp, 3000); att = (GF_X_Attribute*)malloc(sizeof(GF_X_Attribute)); att->Name = strdup(comp); att->Value = NULL; pos += 1; if (buffer[pos] == ' ') pos += 1; pos = gf_token_get(buffer, pos, "\r\n", comp, 3000); if (pos > 0) att->Value = strdup(comp); if (media) { gf_list_add(media->Attributes, att); } else { gf_list_add(sdp->Attributes, att); }}#define SDPM_DESTROY(p) if (media->p) free(media->p)GF_EXPORTvoid gf_sdp_media_del(GF_SDPMedia *media){ GF_SDPBandwidth *bw; GF_RTPMap *map; GF_SDPConnection *conn; GF_SDP_FMTP *fmtp; GF_X_Attribute *att; if (!media) return; while (gf_list_count(media->FMTP)) { fmtp = (GF_SDP_FMTP*)gf_list_get(media->FMTP, 0); gf_list_rem(media->FMTP, 0); gf_sdp_fmtp_del(fmtp); } gf_list_del(media->FMTP); while (gf_list_count(media->Attributes)) { att = (GF_X_Attribute*)gf_list_get(media->Attributes, 0); gf_list_rem(media->Attributes, 0); if (att->Name) free(att->Name); if (att->Value) free(att->Value); free(att); } gf_list_del(media->Attributes); while (gf_list_count(media->RTPMaps)) { map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0); free(map->payload_name); free(map); gf_list_rem(media->RTPMaps, 0); } gf_list_del(media->RTPMaps); while (gf_list_count(media->Connections)) { conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0); gf_list_rem(media->Connections, 0); gf_sdp_conn_del(conn); } gf_list_del(media->Connections); while (gf_list_count(media->Bandwidths)) { bw = (GF_SDPBandwidth*)gf_list_get(media->Bandwidths, 0); gf_list_rem(media->Bandwidths, 0); if (bw->name) free(bw->name); free(bw); } gf_list_del(media->Bandwidths); SDPM_DESTROY(orientation); SDPM_DESTROY(sdplang); SDPM_DESTROY(lang); SDPM_DESTROY(Profile); SDPM_DESTROY(fmt_list); SDPM_DESTROY(k_method); SDPM_DESTROY(k_key); free(media);}GF_EXPORTGF_SDPConnection *gf_sdp_conn_new(){ GF_SDPConnection *conn; GF_SAFEALLOC(conn, GF_SDPConnection); conn->TTL = -1; return conn;}GF_EXPORTvoid gf_sdp_conn_del(GF_SDPConnection *conn){ if (conn->add_type) free(conn->add_type); if (conn->host) free(conn->host); if (conn->net_type) free(conn->net_type); free(conn);}GF_EXPORTGF_SDPMedia *gf_sdp_media_new(){ GF_SDPMedia *tmp; GF_SAFEALLOC(tmp, GF_SDPMedia); tmp->FMTP = gf_list_new(); tmp->RTPMaps = gf_list_new(); tmp->Attributes = gf_list_new(); tmp->Connections = gf_list_new(); tmp->Bandwidths = gf_list_new(); tmp->Quality = -1; return tmp;}GF_EXPORTGF_SDPInfo *gf_sdp_info_new(){ GF_SDPInfo *sdp; GF_SAFEALLOC(sdp, GF_SDPInfo); sdp->b_bandwidth = gf_list_new(); sdp->media_desc = gf_list_new(); sdp->Attributes = gf_list_new(); sdp->Timing = gf_list_new(); return sdp;}#define SDP_DESTROY(p) if (sdp->p) \ free(sdp->p); \ sdp->p = NULL;GF_EXPORTvoid gf_sdp_info_reset(GF_SDPInfo *sdp){ GF_SDPBandwidth *bw; GF_SDPMedia *media; GF_SDPTiming *timing; GF_X_Attribute *att; if (!sdp) return; while (gf_list_count(sdp->media_desc)) { media = (GF_SDPMedia*)gf_list_get(sdp->media_desc, 0); gf_list_rem(sdp->media_desc, 0); gf_sdp_media_del(media); } while (gf_list_count(sdp->Attributes)) { att = (GF_X_Attribute*)gf_list_get(sdp->Attributes, 0); gf_list_rem(sdp->Attributes, 0); if (att->Name) free(att->Name); if (att->Value) free(att->Value); free(att); } while (gf_list_count(sdp->b_bandwidth)) { bw = (GF_SDPBandwidth*)gf_list_get(sdp->b_bandwidth, 0); gf_list_rem(sdp->b_bandwidth, 0); if (bw->name) free(bw->name); free(bw); } while (gf_list_count(sdp->Timing)) { timing = (GF_SDPTiming*)gf_list_get(sdp->Timing, 0); gf_list_rem(sdp->Timing, 0); free(timing); } //then delete all info ... SDP_DESTROY(o_username); SDP_DESTROY(o_session_id); SDP_DESTROY(o_version); SDP_DESTROY(o_address); SDP_DESTROY(o_net_type); SDP_DESTROY(o_add_type); SDP_DESTROY(s_session_name); SDP_DESTROY(i_description); SDP_DESTROY(u_uri); SDP_DESTROY(e_email); SDP_DESTROY(p_phone); SDP_DESTROY(k_method); SDP_DESTROY(k_key); SDP_DESTROY(a_cat); SDP_DESTROY(a_keywds); SDP_DESTROY(a_tool); SDP_DESTROY(a_type); SDP_DESTROY(a_charset); SDP_DESTROY(a_sdplang); SDP_DESTROY(a_lang); if (sdp->c_connection) { gf_sdp_conn_del(sdp->c_connection); sdp->c_connection = NULL; } sdp->a_SendRecieve = 0;}GF_EXPORTvoid gf_sdp_info_del(GF_SDPInfo *sdp){ if (!sdp) return; gf_sdp_info_reset(sdp); gf_list_del(sdp->media_desc); gf_list_del(sdp->Attributes); gf_list_del(sdp->b_bandwidth); gf_list_del(sdp->Timing); free(sdp);}Bool SDP_IsDynamicPayload(GF_SDPMedia *media, char *payt){ u32 i; GF_RTPMap *map; char buf[10]; i=0; while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &i))) { sprintf(buf, "%d", map->PayloadType); if (!strcmp(payt, buf)) return 1; } return 0;}//translate h || m || d in sec. Fractions are not allowed with this writing s32 SDP_MakeSeconds(char *buf){ s32 sign; char num[30], *test; sign = 1; if (buf[0] == '-') { sign = -1; buf += 1; } memset(num, 0, 30); test = strstr(buf, "d"); if (test) { strncpy(num, buf, strlen(buf)-strlen(test)); return (atoi(num)*sign*86400); } test = strstr(buf, "h"); if (test) { strncpy(num, buf, strlen(buf)-strlen(test)); return (atoi(num)*sign*3600); } test = strstr(buf, "m"); if (test) { strncpy(num, buf, strlen(buf)-strlen(test)); return (atoi(num)*sign*60); } return (atoi(buf) * sign);}GF_EXPORTGF_Err gf_sdp_info_parse(GF_SDPInfo *sdp, char *sdp_text, u32 text_size){ GF_SDPBandwidth *bw; GF_SDPConnection *conn; GF_SDPMedia *media; GF_SDPTiming *timing; u32 i; s32 pos, LinePos; char LineBuf[3000], comp[3000]; media = NULL; timing = NULL; if (!sdp) return GF_BAD_PARAM; //Clean SDP info gf_sdp_info_reset(sdp); LinePos = 0; while (1) { LinePos = gf_token_get_line(sdp_text, LinePos, text_size, LineBuf, 3000); if (LinePos <= 0) break; if (!strcmp(LineBuf, "\r\n") || !strcmp(LineBuf, "\n") || !strcmp(LineBuf, "\r")) continue; switch (LineBuf[0]) { case 'v': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->Version = atoi(comp); break; case 'o': pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000); sdp->o_username = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_session_id = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_version = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_net_type = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_add_type = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_address = strdup(comp); break; case 's': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->s_session_name = strdup(comp); break; case 'i': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->i_description = strdup(comp); break; case 'u': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->u_uri = strdup(comp); break; case 'e': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->e_email = strdup(comp); break; case 'p': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->p_phone = strdup(comp); break; case 'c': //if at session level, only 1 is allowed for all SDP if (sdp->c_connection) break; conn = gf_sdp_conn_new(); pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000); conn->net_type = strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); conn->add_type = strdup(comp); pos = gf_token_get(LineBuf, pos, " /\r\n", comp, 3000); conn->host = strdup(comp); if (gf_sk_is_multicast_address(conn->host)) { //a valid SDP will have TTL if address is multicast pos = gf_token_get(LineBuf, pos, "/\r\n", comp, 3000); if (pos <= 0) { gf_sdp_conn_del(conn); break; } conn->TTL = atoi(comp); //multiple address indication is only valid for media pos = gf_token_get(LineBuf, pos, "/\r\n", comp, 3000); if (pos > 0) { if (!media) { gf_sdp_conn_del(conn); break; } conn->add_count = atoi(comp); } } if (!media) sdp->c_connection = conn; else gf_list_add(media->Connections, conn); break; case 'b': pos = gf_token_get(LineBuf, 2, ":\r\n", comp, 3000); if (strcmp(comp, "CT") && strcmp(comp, "AS") && (comp[0] != 'X')) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -