📄 sdp.c
字号:
bw = (GF_SDPBandwidth*)malloc(sizeof(GF_SDPBandwidth)); bw->name = strdup(comp); pos = gf_token_get(LineBuf, pos, ":\r\n", comp, 3000); bw->value = atoi(comp); if (media) { gf_list_add(media->Bandwidths, bw); } else { gf_list_add(sdp->b_bandwidth, bw); } break; case 't': if (media) break; //create a new time structure for each entry GF_SAFEALLOC(timing, GF_SDPTiming); pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000); timing->StartTime = atoi(comp); pos = gf_token_get(LineBuf, pos, "\r\n", comp, 3000); timing->StopTime = atoi(comp); gf_list_add(sdp->Timing, timing); break; case 'r': if (media) break; pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000); timing->RepeatInterval = SDP_MakeSeconds(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); timing->ActiveDuration = SDP_MakeSeconds(comp); while (1) { pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); if (pos <= 0) break; timing->OffsetFromStart[timing->NbRepeatOffsets] = SDP_MakeSeconds(comp); timing->NbRepeatOffsets += 1; } break; case 'z': if (media) break; pos = 2; while (1) { pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); if (pos <= 0) break; timing->AdjustmentTime[timing->NbZoneOffsets] = atoi(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); timing->AdjustmentOffset[timing->NbZoneOffsets] = SDP_MakeSeconds(comp); timing->NbZoneOffsets += 1; } break; case 'k': pos = gf_token_get(LineBuf, 2, ":\t\r\n", comp, 3000); if (media) { media->k_method = strdup(comp); } else { sdp->k_method = strdup(comp); } pos = gf_token_get(LineBuf, pos, ":\r\n", comp, 3000); if (pos > 0) { if (media) { media->k_key = strdup(comp); } else { sdp->k_key = strdup(comp); } } break; case 'a': SDP_ParseAttribute(sdp, LineBuf+2, media); break; case 'm': pos = gf_token_get(LineBuf, 2, " \t\r\n", comp, 3000); if (strcmp(comp, "audio") && strcmp(comp, "data") && strcmp(comp, "control") && strcmp(comp, "video") && strcmp(comp, "text") && strcmp(comp, "application")) { return GF_SERVICE_ERROR; } media = gf_sdp_media_new(); //media type if (!strcmp(comp, "video")) media->Type = 1; else if (!strcmp(comp, "audio")) media->Type = 2; else if (!strcmp(comp, "text")) media->Type = 3; else if (!strcmp(comp, "data")) media->Type = 4; else if (!strcmp(comp, "control")) media->Type = 5; else media->Type = 0; //port numbers gf_token_get(LineBuf, pos, " ", comp, 3000); if (!strstr(comp, "/")) { pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000); media->PortNumber = atoi(comp); media->NumPorts = 0; } else { pos = gf_token_get(LineBuf, pos, " /\r\n", comp, 3000); media->PortNumber = atoi(comp); pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000); media->NumPorts = atoi(comp); } //transport Profile pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000); media->Profile = strdup(comp); pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000); media->fmt_list = strdup(comp); gf_list_add(sdp->media_desc, media); break; } } //finally rewrite the fmt_list for all media, and remove dynamic payloads //from the list i=0; while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) { pos = 0; LinePos = 1; strcpy(LineBuf, ""); while (1) { if (!media->fmt_list) break; pos = gf_token_get(media->fmt_list, pos, " ", comp, 3000); if (pos <= 0) break; if (!SDP_IsDynamicPayload(media, comp)) { if (!LinePos) { strcat(LineBuf, " "); } else { LinePos = 0; } strcat(LineBuf, comp); } free(media->fmt_list); media->fmt_list = NULL; if (strlen(LineBuf)) { media->fmt_list = strdup(LineBuf); } } } return GF_OK;}GF_Err SDP_CheckConnection(GF_SDPConnection *conn){ if (!conn) return GF_BAD_PARAM; if (!conn->host || !conn->add_type || !conn->net_type) return GF_REMOTE_SERVICE_ERROR; if (gf_sk_is_multicast_address(conn->host)) { if (conn->TTL < 0 || conn->TTL > 255) return GF_REMOTE_SERVICE_ERROR; } else { conn->TTL = -1; conn->add_count = 0; } return GF_OK;}//return GF_BAD_PARAM if invalid structure, GF_REMOTE_SERVICE_ERROR if bad formatting//or GF_OKGF_EXPORTGF_Err gf_sdp_info_check(GF_SDPInfo *sdp){ GF_Err e; u32 i, j, count; GF_SDPMedia *media; GF_SDPConnection *conn; GF_RTPMap *map; Bool HasGlobalConnection, HasSeveralPorts; if (!sdp || !sdp->media_desc || !sdp->Attributes) return GF_BAD_PARAM; //we force at least one media per SDP if (!gf_list_count(sdp->media_desc)) return GF_REMOTE_SERVICE_ERROR; //normative fields //o= if (!sdp->o_add_type || !sdp->o_address || !sdp->o_username || !sdp->o_session_id || !sdp->o_version) return GF_REMOTE_SERVICE_ERROR; //s= if (!sdp->s_session_name) return GF_REMOTE_SERVICE_ERROR; //t=// if () return GF_REMOTE_SERVICE_ERROR; //c= if (sdp->c_connection) { e = SDP_CheckConnection(sdp->c_connection); if (e) return e; //multiple addresses are only for media desc if (sdp->c_connection->add_count >= 2) return GF_REMOTE_SERVICE_ERROR; HasGlobalConnection = 1; } else { HasGlobalConnection = 0; } //then check all media i=0; while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) { HasSeveralPorts = 0; //m= : force non-null port, profile and fmt_list if (!media->PortNumber || !media->Profile) return GF_REMOTE_SERVICE_ERROR; if (media->NumPorts) HasSeveralPorts = 1; //no connections specified - THIS IS AN ERROR IN SDP BUT NOT IN ALL RTSP SESSIONS...// if (!HasGlobalConnection && !gf_list_count(media->Connections)) return GF_REMOTE_SERVICE_ERROR; //too many connections specified if (HasGlobalConnection && gf_list_count(media->Connections)) return GF_REMOTE_SERVICE_ERROR; //check all connections, and make sure we don't have multiple addresses //and multiple ports at the same time count = gf_list_count(media->Connections); if (count>1 && HasSeveralPorts) return GF_REMOTE_SERVICE_ERROR; for (j=0; j<count; j++) { conn = (GF_SDPConnection*)gf_list_get(media->Connections, j); e = SDP_CheckConnection(conn); if (e) return e; if ((conn->add_count >= 2) && HasSeveralPorts) return GF_REMOTE_SERVICE_ERROR; } //RTPMaps. 0 is tolerated, but if some are specified check them j=0; while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) { //RFC2327 is not clear here, but we assume the PayloadType should be a DYN one //however this depends on the profile (RTP/AVP or others) so don't check it //ClockRate SHALL NOT be NULL if (!map->payload_name || !map->ClockRate) return GF_REMOTE_SERVICE_ERROR; } } //Encryption: nothing tells wether the scope of the global key is eclusive or not. //we accept a global key + keys per media entry, assuming that the media key primes //on the global key return GF_OK;}#define SDP_WRITE_ALLOC_STR(str, space) \ if (str) { \ if (strlen(str)+pos + (space ? 1 : 0) >= buf_size) { \ buf_size += SDP_WRITE_STEPALLOC; \ buf = (char*)realloc(buf, sizeof(char)*buf_size); \ } \ strcpy(buf+pos, str); \ pos += strlen(str); \ if (space) { \ strcat(buf+pos, " "); \ pos += 1; \ } \ }#define SDP_WRITE_ALLOC_INT(d, spa, sig) \ if (sig) { \ sprintf(temp, "%d", d); \ } else { \ sprintf(temp, "%u", d); \ } \ SDP_WRITE_ALLOC_STR(temp, spa);#define SDP_WRITE_ALLOC_FLOAT(d, spa) \ sprintf(temp, "%.2f", d); \ SDP_WRITE_ALLOC_STR(temp, spa);#define TEST_SDP_WRITE_SINGLE(type, str, sep) \ if (str) { \ SDP_WRITE_ALLOC_STR(type, 0); \ if (sep) SDP_WRITE_ALLOC_STR(":", 0); \ SDP_WRITE_ALLOC_STR(str, 0); \ SDP_WRITE_ALLOC_STR("\r\n", 0); \ }#define SDP_WRITE_CONN(conn) \ if (conn) { \ SDP_WRITE_ALLOC_STR("c=", 0); \ SDP_WRITE_ALLOC_STR(conn->net_type, 1); \ SDP_WRITE_ALLOC_STR(conn->add_type, 1); \ SDP_WRITE_ALLOC_STR(conn->host, 0); \ if (gf_sk_is_multicast_address(conn->host)) { \ SDP_WRITE_ALLOC_STR("/", 0); \ SDP_WRITE_ALLOC_INT(conn->TTL, 0, 0); \ if (conn->add_count >= 2) { \ SDP_WRITE_ALLOC_STR("/", 0); \ SDP_WRITE_ALLOC_INT(conn->add_count, 0, 0); \ } \ } \ SDP_WRITE_ALLOC_STR("\r\n", 0); \ }GF_EXPORTGF_Err gf_sdp_info_write(GF_SDPInfo *sdp, char **out_str_buf){ char *buf; GF_SDP_FMTP *fmtp; char temp[50]; GF_SDPMedia *media; GF_SDPBandwidth *bw; u32 buf_size, pos, i, j, k; GF_RTPMap *map; GF_SDPConnection *conn; GF_Err e; GF_SDPTiming *timing; GF_X_Attribute *att; e = gf_sdp_info_check(sdp); if (e) return e; buf = (char *)malloc(SDP_WRITE_STEPALLOC); buf_size = SDP_WRITE_STEPALLOC; pos = 0; //v SDP_WRITE_ALLOC_STR("v=", 0); SDP_WRITE_ALLOC_INT(sdp->Version, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); //o SDP_WRITE_ALLOC_STR("o=", 0); SDP_WRITE_ALLOC_STR(sdp->o_username, 1); SDP_WRITE_ALLOC_STR(sdp->o_session_id, 1); SDP_WRITE_ALLOC_STR(sdp->o_version, 1); SDP_WRITE_ALLOC_STR(sdp->o_net_type, 1); SDP_WRITE_ALLOC_STR(sdp->o_add_type, 1); SDP_WRITE_ALLOC_STR(sdp->o_address, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); //s TEST_SDP_WRITE_SINGLE("s=", sdp->s_session_name, 0); //i TEST_SDP_WRITE_SINGLE("i=", sdp->i_description, 0); //u TEST_SDP_WRITE_SINGLE("u=", sdp->u_uri, 0); //e TEST_SDP_WRITE_SINGLE("e=", sdp->e_email, 0); //p TEST_SDP_WRITE_SINGLE("p=", sdp->p_phone, 0); //c SDP_WRITE_CONN(sdp->c_connection); //b i=0; while ((bw = (GF_SDPBandwidth*)gf_list_enum(sdp->b_bandwidth, &i))) { SDP_WRITE_ALLOC_STR("b=", 0); SDP_WRITE_ALLOC_STR(bw->name, 0); SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_INT(bw->value, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); } //t+r+z i=0; while ((timing = (GF_SDPTiming*)gf_list_enum(sdp->Timing, &i))) { if (timing->NbRepeatOffsets > GF_SDP_MAX_TIMEOFFSET) timing->NbRepeatOffsets = GF_SDP_MAX_TIMEOFFSET; if (timing->NbZoneOffsets > GF_SDP_MAX_TIMEOFFSET) timing->NbZoneOffsets = GF_SDP_MAX_TIMEOFFSET; //t SDP_WRITE_ALLOC_STR("t=", 0); SDP_WRITE_ALLOC_INT(timing->StartTime, 1, 0); SDP_WRITE_ALLOC_INT(timing->StopTime, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); if (timing->NbRepeatOffsets) { SDP_WRITE_ALLOC_STR("r=", 0); SDP_WRITE_ALLOC_INT(timing->RepeatInterval, 1, 0); SDP_WRITE_ALLOC_INT(timing->ActiveDuration, 0, 0); for (j=0; j<timing->NbRepeatOffsets; j++) { SDP_WRITE_ALLOC_STR(" ", 0); SDP_WRITE_ALLOC_INT(timing->OffsetFromStart[j], 0, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } if (timing->NbZoneOffsets) { SDP_WRITE_ALLOC_STR("z=", 0); for (j=0; j<timing->NbZoneOffsets; j++) { SDP_WRITE_ALLOC_INT(timing->AdjustmentTime[j], 1, 0); if (j+1 == timing->NbRepeatOffsets) { SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 0, 1); } else { SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 1, 1); } } SDP_WRITE_ALLOC_STR("\r\n", 0); } } //k if (sdp->k_method) { SDP_WRITE_ALLOC_STR("k=", 0); SDP_WRITE_ALLOC_STR(sdp->k_method, 0); if (sdp->k_key) { SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_STR(sdp->k_key, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=cat TEST_SDP_WRITE_SINGLE("a=cat", sdp->a_cat, 1); //a=keywds TEST_SDP_WRITE_SINGLE("a=keywds", sdp->a_keywds, 1); //a=tool TEST_SDP_WRITE_SINGLE("a=tool", sdp->a_tool, 1); //a=SendRecv switch (sdp->a_SendRecieve) { case 1: TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0); break; case 2: TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0); break; case 3: TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0); break; default: break; } //a=type TEST_SDP_WRITE_SINGLE("a=type", sdp->a_type, 1); //a=charset TEST_SDP_WRITE_SINGLE("a=charset", sdp->a_charset, 1); //a=sdplang TEST_SDP_WRITE_SINGLE("a=sdplang", sdp->a_sdplang, 1); //a=lang TEST_SDP_WRITE_SINGLE("a=lang", sdp->a_lang, 1); //the rest i=0; while ((att = (GF_X_Attribute*)gf_list_enum(sdp->Attributes, &i))) { SDP_WRITE_ALLOC_STR("a=", 0); SDP_WRITE_ALLOC_STR(att->Name, 0); if (att->Value) { SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_STR(att->Value, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } //now write media specific i=0; while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) { //m= SDP_WRITE_ALLOC_STR("m=", 0); switch (media->Type) { case 1: SDP_WRITE_ALLOC_STR("video", 1); break; case 2: SDP_WRITE_ALLOC_STR("audio", 1); break; case 3: SDP_WRITE_ALLOC_STR("data", 1); break; case 4: SDP_WRITE_ALLOC_STR("control", 1); break; default: SDP_WRITE_ALLOC_STR("application", 1); break; } SDP_WRITE_ALLOC_INT(media->PortNumber, 0, 0); if (media->NumPorts >= 2) { SDP_WRITE_ALLOC_STR("/", 0); SDP_WRITE_ALLOC_INT(media->NumPorts, 1, 0); } else { SDP_WRITE_ALLOC_STR(" ", 0); } SDP_WRITE_ALLOC_STR(media->Profile, 1); SDP_WRITE_ALLOC_STR(media->fmt_list, 0); j=0; while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) { SDP_WRITE_ALLOC_STR(" ", 0); SDP_WRITE_ALLOC_INT(map->PayloadType, 0, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); //c= j=0; while ((conn = (GF_SDPConnection*)gf_list_enum(media->Connections, &j))) { SDP_WRITE_CONN(conn); } //k= if (media->k_method) { SDP_WRITE_ALLOC_STR("k=", 0); SDP_WRITE_ALLOC_STR(media->k_method, 0); if (media->k_key) { SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_STR(media->k_key, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } //b j=0; while ((bw = (GF_SDPBandwidth*)gf_list_enum(media->Bandwidths, &j))) { SDP_WRITE_ALLOC_STR("b=", 0); SDP_WRITE_ALLOC_STR(bw->name, 0); SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_INT(bw->value, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=rtpmap j=0; while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) { SDP_WRITE_ALLOC_STR("a=rtpmap", 0); SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_INT(map->PayloadType, 1, 0); SDP_WRITE_ALLOC_STR(map->payload_name, 0); SDP_WRITE_ALLOC_STR("/", 0); SDP_WRITE_ALLOC_INT(map->ClockRate, 0, 0); if (map->AudioChannels > 1) { SDP_WRITE_ALLOC_STR("/", 0); SDP_WRITE_ALLOC_INT(map->AudioChannels, 0, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=fmtp j=0; while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &j))) { SDP_WRITE_ALLOC_STR("a=fmtp:", 0); SDP_WRITE_ALLOC_INT(fmtp->PayloadType, 1 , 0); k=0; while ((att = (GF_X_Attribute*)gf_list_enum(fmtp->Attributes, &k)) ) { if (k>1) SDP_WRITE_ALLOC_STR(";", 0); SDP_WRITE_ALLOC_STR(att->Name, 0); if (att->Value) { SDP_WRITE_ALLOC_STR("=", 0); SDP_WRITE_ALLOC_STR(att->Value, 0); } } SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=ptime if (media->PacketTime) { SDP_WRITE_ALLOC_STR("a=ptime:", 0); SDP_WRITE_ALLOC_INT(media->PacketTime, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=FrameRate if (media->Type == 1 && media->FrameRate) { SDP_WRITE_ALLOC_STR("a=framerate:", 0); SDP_WRITE_ALLOC_FLOAT(media->FrameRate, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); } //a=SendRecv switch (media->SendRecieve) { case 1: TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0); break; case 2: TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0); break; case 3: TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0); break; default: break; } //a=orient TEST_SDP_WRITE_SINGLE("a=orient", media->orientation, 1); //a=sdplang TEST_SDP_WRITE_SINGLE("a=sdplang", media->sdplang, 1); //a=lang TEST_SDP_WRITE_SINGLE("a=lang", media->lang, 1); //a=quality if (media->Quality >= 0) { SDP_WRITE_ALLOC_STR("a=quality:", 0); SDP_WRITE_ALLOC_INT(media->Quality, 0, 0); SDP_WRITE_ALLOC_STR("\r\n", 0); } //the rest j=0; while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &j))) { SDP_WRITE_ALLOC_STR("a=", 0); SDP_WRITE_ALLOC_STR(att->Name, 0); if (att->Value) { SDP_WRITE_ALLOC_STR(":", 0); SDP_WRITE_ALLOC_STR(att->Value, 0); } SDP_WRITE_ALLOC_STR("\r\n", 0); } } //finally realloc //finall NULL char pos += 1; buf = (char *)realloc(buf, pos); *out_str_buf = buf; return GF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -