📄 sdp_parse.c
字号:
sdp_rtpmap_celb = RTPMAP(25, "CelB", 90000, 0), sdp_rtpmap_jpeg = RTPMAP(26, "JPEG", 90000, 0), sdp_rtpmap_nv = RTPMAP(28, "nv", 90000, 0), sdp_rtpmap_h261 = RTPMAP(31, "H261", 90000, 0), sdp_rtpmap_mpv = RTPMAP(32, "MPV", 90000, 0), sdp_rtpmap_mp2t = RTPMAP(33, "MP2T", 90000, 0), sdp_rtpmap_h263 = RTPMAP(34, "H263", 90000, 0);/** Table of rtpmap structures by payload type numbers. * * The table of reserved payload numbers is constructed from @RFC3551 * and @RFC1890. Note the clock rate of G722. * * Use sdp_rtpmap_dup() to copy these structures. */sdp_rtpmap_t const * const sdp_rtpmap_well_known[128] ={ &sdp_rtpmap_pcmu, /* 0 */ &sdp_rtpmap_1016, /* 1 */ &sdp_rtpmap_g721, /* 2 */ &sdp_rtpmap_gsm, /* 3 */ &sdp_rtpmap_g723, /* 4 */ &sdp_rtpmap_dvi4_8000, /* 5 */ &sdp_rtpmap_dvi4_16000, /* 6 */ &sdp_rtpmap_lpc, /* 7 */ &sdp_rtpmap_pcma, /* 8 */ &sdp_rtpmap_g722, /* 9 */ &sdp_rtpmap_l16_2, /* 10 */ &sdp_rtpmap_l16, /* 11 */ &sdp_rtpmap_qcelp, /* 12 */ &sdp_rtpmap_cn, /* 13 */ &sdp_rtpmap_mpa, /* 14 */ &sdp_rtpmap_g728, /* 15 */ &sdp_rtpmap_dvi4_11025, /* 16 */ &sdp_rtpmap_dvi4_22050, /* 17 */ &sdp_rtpmap_g729, /* 18 */ &sdp_rtpmap_reserved_cn, /* 19 */ NULL, /* 20 */ NULL, /* 21 */ NULL, /* 22 */ NULL, /* 23 */ NULL, /* 24 */ &sdp_rtpmap_celb, /* 25 */ &sdp_rtpmap_jpeg, /* 26 */ NULL, /* 27 */ &sdp_rtpmap_nv, /* 28 */ NULL, /* 29 */ NULL, /* 30 */ &sdp_rtpmap_h261, /* 31 */ &sdp_rtpmap_mpv, /* 32 */ &sdp_rtpmap_mp2t, /* 33 */ &sdp_rtpmap_h263, /* 34 */ NULL,};/** * The function parse_payload() parses an RTP payload type list, and * creates an rtpmap structure for each payload type. * * @param p pointer to SDP parser object * @param r pointer to record data * @param result pointer to which parsed record is assigned */static void parse_payload(sdp_parser_t *p, char *r, sdp_rtpmap_t **result){ while (*r) { unsigned long value; if (parse_ul(p, &r, &value, 128) == 0) { PARSE_ALLOC(p, sdp_rtpmap_t, rm); assert(0 <= value && value < 128); *result = rm; result = &rm->rm_next; if (sdp_rtpmap_well_known[value]) { *rm = *sdp_rtpmap_well_known[value]; } else { rm->rm_predef = 1; rm->rm_pt = value; rm->rm_encoding = ""; rm->rm_rate = 0; } } else if (p->pr_config && r[0] == '*' && (r[1] == ' ' || r[1] == '\0')) { PARSE_ALLOC(p, sdp_rtpmap_t, rm); *result = rm; result = &rm->rm_next; rm->rm_predef = 1; rm->rm_any = 1; rm->rm_encoding = "*"; rm->rm_rate = 0; return; } else { parsing_error(p, "m= invalid format for RTP/AVT"); return; } }}/* ------------------------------------------------------------------------- * Function parse_media_attr() - parse a media-specific "a=" field * * Description: * This function parses a media-specific attribute field. * * Parameters: * p - pointer to SDP parser object * r - pointer to record data * result - pointer to which parsed record is assigned */static void parse_media_attr(sdp_parser_t *p, char *r, sdp_media_t *m, sdp_attribute_t **result){ /* attribute-fields = *("a=" attribute CRLF) attribute = (att-field ":" att-value) | att-field att-field = 1*(alpha-numeric) att-value = byte-string a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding parameters>] a=fmtp:<payload type> <parameters> */ int rtp = sdp_media_has_rtp(m); char *name = NULL, *value = NULL; int n; if (!(name = token(&r, ":", ALPHA DIGIT "-", SPACE TAB))) { parsing_error(p,"invalid attribute name"); return; } if (*r) value = r; else PARSE_CHECK_REST(p, r, "a"); if (p->pr_mode_manual) ; else if (strcasecmp(name, "inactive") == 0) { m->m_mode = sdp_inactive; return; } else if (strcasecmp(name, "sendonly") == 0) { m->m_mode = sdp_sendonly; return; } else if (strcasecmp(name, "recvonly") == 0) { m->m_mode = sdp_recvonly; return; } else if (strcasecmp(name, "sendrecv") == 0) { m->m_mode = sdp_sendrecv; return; } if (rtp && strcasecmp(name, "rtpmap") == 0) { if ((n = parse_rtpmap(p, r, m)) == 0 || n < -1) return; } else if (rtp && strcasecmp(name, "fmtp") == 0) { if ((n = parse_fmtp(p, r, m)) == 0 || n < -1) return; } else { PARSE_ALLOC(p, sdp_attribute_t, a); *result = a; a->a_name = name; a->a_value = value; }}/** Parse rtpmap attribute. * * a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding parameters>] */static int parse_rtpmap(sdp_parser_t *p, char *r, sdp_media_t *m){ unsigned long pt, rate; char *encoding, *params; sdp_rtpmap_t *rm; int strict = STRICT(p); if (parse_ul(p, &r, &pt, 128)) { if (strict) parsing_error(p, "a=rtpmap: invalid payload type"); return -1; } for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) if (rm->rm_pt == pt) break; if (!rm) { if (strict) parsing_error(p, "a=rtpmap:%lu: unknown payload type", pt); return -1; } encoding = token(&r, "/", ALPHA DIGIT "-", NULL); if (!r) { parsing_error(p, "a=rtpmap:%lu: missing <clock rate>", pt); return -2; } if (parse_ul(p, &r, &rate, 0)) { parsing_error(p, "a=rtpmap:%lu %s: invalid <clock rate>", pt, encoding); return -2; } if (*r == '/') params = ++r; else params = 0; rm->rm_predef = 0; rm->rm_encoding = encoding; rm->rm_rate = rate; rm->rm_params = params; return 0;}/** Parse fmtp attribute. * * a=fmtp:<payload type> <parameters> */static int parse_fmtp(sdp_parser_t *p, char *r, sdp_media_t *m){ unsigned long pt; sdp_rtpmap_t *rm; int strict = STRICT(p); if (parse_ul(p, &r, &pt, 128)) { if (strict) parsing_error(p, "a=rtpmap: invalid payload type"); return -1; } for (rm = m->m_rtpmaps; rm; rm = rm->rm_next) if (rm->rm_pt == pt) break; if (!rm) { if (strict) parsing_error(p, "a=fmtp:%lu: unknown payload type", pt); return -1; } rm->rm_fmtp = r; return 0;}/* ------------------------------------------------------------------------- * Function parse_descs() - parse media descriptors * * Description: * This function parses media descriptors at the end of SDP message. * * Parameters: * p - pointer to SDP parser object * record - pointer to first media field * message - pointer to rest * medias - pointer to which parsed media structures are assigned */static void parse_descs(sdp_parser_t *p, char *record, char *message, sdp_media_t **medias){ char *rest; const char *strip; sdp_media_t *m = NULL; sdp_connection_t **connections = NULL; sdp_bandwidth_t **bandwidths = NULL; sdp_attribute_t **attributes = NULL; if (!STRICT(p)) strip = SPACE TAB; /* skip initial whitespace */ else strip = ""; for (; record && p->pr_ok; record = next(&message, CRLF, strip)) { char field = record[0]; rest = record + 2; rest += strspn(rest, strip); if (record[1] == '=') switch (field) { case 'c': assert(connections); parse_connection(p, rest, connections); connections = &(*connections)->c_next; break; case 'b': assert(bandwidths); parse_bandwidth(p, rest, bandwidths); bandwidths = &(*bandwidths)->b_next; break; case 'k': parse_key(p, rest, &m->m_key); break; case 'a': assert(attributes); parse_media_attr(p, rest, m, attributes); if (*attributes) attributes = &(*attributes)->a_next; break; case 'm': parse_media(p, rest, medias); m = *medias; if (m) { m->m_mode = p->pr_session_mode; medias = &m->m_next; connections = &m->m_connections; bandwidths = &m->m_bandwidths; attributes = &m->m_attributes; } } }}static void parse_text_list(sdp_parser_t *p, char *r, sdp_list_t **result){ PARSE_ALLOC(p, sdp_list_t, l); *result = l; l->l_text = r;}/* * parse_ul: parse an unsigned long */static int parse_ul(sdp_parser_t *p, char **r, unsigned long *result, unsigned long max){ char *ul = *r; ul += strspn(ul, SPACE TAB); *result = strtoul(ul, r, 10); if (ul != *r && !(max && max <= *result)) { *r += strspn(*r, SPACE TAB); return 0; } return -1;}#if !HAVE_STRTOULLunsigned longlong strtoull(char const *string, char **return_end, int base);#endif/* * parse_ull: parse an unsigned long long */static int parse_ull(sdp_parser_t *p, char **r, uint64_t *result, uint64_t max){ unsigned longlong ull; char *s = *r; s += strspn(s, SPACE TAB); ull = strtoull(s, r, 10); if (s != *r && !(max && max <= ull)) { *result = (uint64_t)ull; *r += strspn(*r, SPACE TAB); return 0; } return -1;}static char *token(char **message, const char *sep, const char *legal, const char *strip){ size_t n; char *retval = *message; if (strip) retval += strspn(retval, strip); if (legal) n = strspn(retval, legal); else n = strcspn(retval, sep); if (n == 0) return NULL; if (retval[n]) { retval[n++] = '\0'; n += strspn(retval + n, sep); } *message = retval + n; if (*retval == '\0') return NULL; return retval;}static char *next(char **message, const char *sep, const char *strip){ size_t n; char *retval = *message; if (strip[0]) retval += strspn(retval, strip); n = strcspn(retval, sep); if (n == 0) return NULL; if (retval[n]) { retval[n++] = '\0'; n += strspn(retval + n, sep); } *message = retval + n; if (*retval == '\0') return NULL; return retval;}static int parsing_error(sdp_parser_t *p, char const *fmt, ...){ int n; va_list ap; va_start(ap, fmt); memset(p->pr_error, 0, sizeof(p->pr_error)); n = vsnprintf(p->pr_error, sizeof(p->pr_error), fmt, ap); va_end(ap); p->pr_ok = 0; return -1;}static void parse_alloc_error(sdp_parser_t *p, const char *typename){ parsing_error(p, "memory exhausted (while allocating memory for %s)", typename);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -