M4Err SDP_Parse(SDPInfo *sdp, char *sdp_text, u32 text_size) { SDPBandwidth *bw; SDPConnection *conn; SDPMedia *media; SDPTiming *timing; u32 i; s32 pos, LinePos; char LineBuf[3000], comp[3000]; media = NULL; timing = NULL; if (!sdp) return M4BadParam; //Clean SDP info SDP_Reset(sdp); LinePos = 0; while (1) { LinePos = SP_GetOneLine(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 = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000); sdp->Version = atoi(comp); break; case 'o': pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000); sdp->o_username = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_session_id = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_version = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_net_type = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_add_type = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_address = strdup(comp); break; case 's': pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000); sdp->s_session_name = strdup(comp); break; case 'i': pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000); sdp->i_description = strdup(comp); break; case 'u': pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000); sdp->u_uri = strdup(comp); break; case 'e': pos = SP_GetComponent(LineBuf, 2, "\t\r\n", comp, 3000); sdp->e_email = strdup(comp); break; case 'p': pos = SP_GetComponent(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 = SDP_NewConnection(); pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000); conn->net_type = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); conn->add_type = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " /\r\n", comp, 3000); conn->host = strdup(comp); if (SK_IsMulticastAddress(conn->host)) { //a valid SDP will have TTL if address is multicast pos = SP_GetComponent(LineBuf, pos, "/\r\n", comp, 3000); if (pos <= 0) { SDP_DeleteConnection(conn); break; } conn->TTL = atoi(comp); //multiple address indication is only valid for media pos = SP_GetComponent(LineBuf, pos, "/\r\n", comp, 3000); if (pos > 0) { if (!media) { SDP_DeleteConnection(conn); break; } conn->add_count = atoi(comp); } } if (!media) sdp->c_connection = conn; else ChainAddEntry(media->Connections, conn); break; case 'b': pos = SP_GetComponent(LineBuf, 2, ":\r\n", comp, 3000); if (strcmp(comp, "CT") && strcmp(comp, "AS") && (comp[0] != 'X')) break; bw = malloc(sizeof(SDPBandwidth)); bw->name = strdup(comp); pos = SP_GetComponent(LineBuf, pos, ":\r\n", comp, 3000); bw->value = atoi(comp); if (media) { ChainAddEntry(media->Bandwidths, bw); } else { ChainAddEntry(sdp->b_bandwidth, bw); } break; case 't': if (media) break; //create a new time structure for each entry timing = malloc(sizeof(SDPTiming)); memset(timing, 0, sizeof(SDPTiming)); pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000); timing->StartTime = atoi(comp); pos = SP_GetComponent(LineBuf, pos, "\r\n", comp, 3000); timing->StopTime = atoi(comp); ChainAddEntry(sdp->Timing, timing); break; case 'r': if (media) break; pos = SP_GetComponent(LineBuf, 2, " \t\r\n", comp, 3000); timing->RepeatInterval = SDP_MakeSeconds(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); timing->ActiveDuration = SDP_MakeSeconds(comp); while (1) { pos = SP_GetComponent(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 = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); if (pos <= 0) break; timing->AdjustmentTime[timing->NbZoneOffsets] = atoi(comp); pos = SP_GetComponent(LineBuf, pos, " \t\r\n", comp, 3000); timing->AdjustmentOffset[timing->NbZoneOffsets] = SDP_MakeSeconds(comp); timing->NbZoneOffsets += 1; } break; case 'k': pos = SP_GetComponent(LineBuf, 2, ":\t\r\n", comp, 3000); if (media) { media->k_method = strdup(comp); } else { sdp->k_method = strdup(comp); } pos = SP_GetComponent(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 = SP_GetComponent(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 M4ServiceError; } media = SDP_NewMedia(); //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 SP_GetComponent(LineBuf, pos, " ", comp, 3000); if (!strstr(comp, "/")) { pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000); media->PortNumber = atoi(comp); media->NumPorts = 0; } else { pos = SP_GetComponent(LineBuf, pos, " /\r\n", comp, 3000); media->PortNumber = atoi(comp); pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000); media->NumPorts = atoi(comp); } //transport Profile pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000); media->Profile = strdup(comp); pos = SP_GetComponent(LineBuf, pos, " \r\n", comp, 3000); media->fmt_list = strdup(comp); ChainAddEntry(sdp->media_desc, media); break; } } //finally rewrite the fmt_list for all media, and remove dynamic payloads //from the list for (i=0; i<ChainGetCount(sdp->media_desc); i++) { media = ChainGetEntry(sdp->media_desc, i); pos = 0; LinePos = 1; strcpy(LineBuf, ""); while (1) { if (!media->fmt_list) break; pos = SP_GetComponent(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 M4OK; }
GF_EXPORT GF_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 = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_session_id = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_version = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_net_type = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_add_type = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); sdp->o_address = gf_strdup(comp); break; case 's': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->s_session_name = gf_strdup(comp); break; case 'i': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->i_description = gf_strdup(comp); break; case 'u': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->u_uri = gf_strdup(comp); break; case 'e': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->e_email = gf_strdup(comp); break; case 'p': pos = gf_token_get(LineBuf, 2, "\t\r\n", comp, 3000); sdp->p_phone = gf_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 = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \t\r\n", comp, 3000); conn->add_type = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " /\r\n", comp, 3000); conn->host = gf_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) { 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; bw = (GF_SDPBandwidth*)gf_malloc(sizeof(GF_SDPBandwidth)); bw->name = gf_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 = gf_strdup(comp); } else { sdp->k_method = gf_strdup(comp); } pos = gf_token_get(LineBuf, pos, ":\r\n", comp, 3000); if (pos > 0) { if (media) { media->k_key = gf_strdup(comp); } else { sdp->k_key = gf_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 = gf_strdup(comp); pos = gf_token_get(LineBuf, pos, " \r\n", comp, 3000); media->fmt_list = gf_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); } gf_free(media->fmt_list); media->fmt_list = NULL; if (strlen(LineBuf)) { media->fmt_list = gf_strdup(LineBuf); } } } return GF_OK; }