📄 sdp_decode.c
字号:
slash = strchr(enc, '/');
if (slash == NULL) {
sdp_debug(LOG_ERR, "Couldn't find / in rtpmap");
return (-1);
}
*slash++ = '\0';
temp = enc;
while ((!(isspace(*temp))) && *temp != '\0') temp++;
*temp = '\0';
// enc points to encode name
ADV_SPACE(slash);
temp = strsep(&slash, " \t/");
if (temp == NULL) {
sdp_debug(LOG_ERR, "Can't find seperator after encode name in rtpmap");
return (-1);
}
if (sscanf(temp, "%u", &a) == 0) {
sdp_debug(LOG_ERR, "Couldn't decode rtp clockrate %s", temp);
return (-1);
}
b = 0;
if (slash != NULL) {
ADV_SPACE(slash);
if (*slash == '/') {
slash++;
ADV_SPACE(slash);
}
if (isdigit(*slash)) {
sscanf(slash, "%u", &b);
}
}
fptr->rtpmap = malloc(sizeof(rtpmap_desc_t));
if (fptr->rtpmap == NULL)
return (-1);
fptr->rtpmap->encode_name = strdup(enc);
fptr->rtpmap->clock_rate = a;
fptr->rtpmap->encode_param = b;
return (0);
}
/*
* sdp_decode_parse_a_cat()
* parses a=category:foo.bar...
*/
static int sdp_decode_parse_a_cat (int arg,
char *orig_line,
session_desc_t *sptr,
media_desc_t *mptr)
{
char *sep, *line, *lptr;
int errret;
uint64_t cat;
category_list_t *cptr, *new;
if (sptr->category_list != NULL) {
return (-1);
}
errret = 0;
cptr = NULL; // shut up compiler
line = strdup(orig_line);
lptr = line;
while ((sep = strsep(&lptr, " \t."))) {
if (*sep != '\0') {
cat = 0;
while (isdigit(*sep)) {
cat *= 10;
cat += *sep - '0';
sep++;
}
if (cat == 0) {
break;
}
new = malloc(sizeof(category_list_t));
if (new == NULL) {
break;
}
new->category = cat;
new->next = NULL;
if (sptr->category_list == NULL) {
cptr = sptr->category_list = new;
} else {
cptr->next = new;
cptr = new;
}
}
}
if (errret != 0) {
free_category_list(&sptr->category_list);
}
free(line);
return (errret);
}
/*
* sdp_decode_parse_a_frame()
* parses a=framerate:<float number>
*/
static int sdp_decode_parse_a_frame (int arg,
char *lptr,
session_desc_t *sptr,
media_desc_t *mptr)
{
char *endptr;
if (mptr == NULL) {
return (-1);
}
mptr->framerate = strtod(lptr, &endptr);
if (endptr == lptr || endptr == NULL) return (-1);
ADV_SPACE(endptr);
if (*endptr != '\0') {
sdp_debug(LOG_ERR, "Garbage at end of frame rate `%s\'", endptr);
return (-1);
}
mptr->framerate_present = TRUE;
return (0);
}
static int convert_npt (char *from, char *to, double *ret)
{
int decimal = FALSE;
double accum;
double mult;
*ret = 0.0;
mult = 0.0;
accum = 0.0;
while ((to == NULL && *from != '\0') || from < to) {
if (isdigit(*from)) {
if (decimal == FALSE) {
accum *= 10.0;
accum += *from - '0';
} else {
accum += ((*from - '0') * mult);
mult /= 10.0;
}
} else if (*from == ':') {
accum *= 60.0;
*ret += accum;
accum = 0;
} else if (*from == '.') {
decimal = TRUE;
mult = .1;
} else {
sdp_debug(LOG_ERR, "Illegal character in NPT string %c", *from);
return (FALSE);
}
from++;
}
*ret += accum;
return (TRUE);
}
static int convert_smpte (char *from, char *to, uint16_t fps, double *ret)
{
int decimal = FALSE;
double accum;
double mult;
unsigned int colon;
*ret = 0.0;
mult = 0.0;
accum = 0.0;
colon = 0;
if (fps == 0) fps = 30;
while ((to == NULL && *from != '\0') || from < to) {
if (isdigit(*from)) {
if (decimal == FALSE) {
accum *= 10.0;
accum += (*from - '0');
} else {
accum += ((*from - '0') * mult);
mult /= 10.0;
}
} else if (*from == ':') {
*ret += accum;
if (colon > 1)
*ret *= fps;
else
*ret *= 60.0;
accum = 0.0;
colon++;
} else if (*from == '.') {
decimal = TRUE;
mult = .1;
} else {
sdp_debug(LOG_ERR, "Illegal character in SMPTE decode %c", *from);
return (FALSE);
}
from++;
}
*ret += accum;
if (colon <= 2) *ret *= fps;
return (TRUE);
}
static int sdp_decode_parse_a_range (int arg,
char *lptr,
session_desc_t *sptr,
media_desc_t *mptr)
{
char *dash;
char *second;
range_desc_t *rptr;
if (mptr == NULL) rptr = &sptr->session_range;
else rptr = &mptr->media_range;
if (rptr->have_range) return (-1);
if (strncasecmp(lptr, "npt", strlen("npt")) == 0) {
lptr += strlen("npt");
rptr->range_is_npt = TRUE;
} else if (strncasecmp(lptr, "smpte", strlen("smpte")) == 0) {
lptr += strlen("smpte");
rptr->range_is_npt = FALSE;
if (*lptr == '-') {
lptr++;
if (strncasecmp(lptr, "30-drop", strlen("30-drop")) == 0) {
rptr->range_smpte_fps = 0;
lptr += strlen("30-drop");
} else {
while (isdigit(*lptr)) {
rptr->range_smpte_fps *= 10;
rptr->range_smpte_fps += *lptr - '0';
lptr++;
}
}
} else {
rptr->range_smpte_fps = 0;
}
} else {
sdp_debug(LOG_ERR, "range decode - unknown keyword %s", lptr);
return (-1);
}
ADV_SPACE(lptr);
if (*lptr != '=') {
sdp_debug(LOG_ERR, "range decode - no =");
return (-1);
}
lptr++;
ADV_SPACE(lptr);
dash = strchr(lptr, '-');
if (dash == NULL) return (-1);
if (rptr->range_is_npt) {
if (convert_npt(lptr, dash, &rptr->range_start) == FALSE) {
sdp_debug(LOG_ERR, "Couldn't decode range from npt %s", lptr);
return (-1);
}
} else {
if (convert_smpte(lptr,
dash,
rptr->range_smpte_fps,
&rptr->range_start) == FALSE) {
sdp_debug(LOG_ERR, "Couldn't decode range from smpte %s", lptr);
return (-1);
}
}
second = dash + 1;
ADV_SPACE(second);
if (*second != '\0') {
if (rptr->range_is_npt) {
if (convert_npt(second, NULL, &rptr->range_end) == FALSE) {
sdp_debug(LOG_ERR, "Couldn't decode range to npt %s", lptr);
return (-1);
}
} else {
if (convert_smpte(second,
NULL,
rptr->range_smpte_fps,
&rptr->range_end) == FALSE) {
sdp_debug(LOG_ERR, "Couldn't decode range to smpte %s", lptr);
return (-1);
}
}
} else {
rptr->range_end_infinite = TRUE;
}
rptr->have_range = TRUE;
return (0);
}
/*
* sdp_decode_parse_a_int()
* parses a=<name>:<uint>
*/
static int sdp_decode_parse_a_int (int arg,
char *orig_line,
session_desc_t *sptr,
media_desc_t *mptr)
{
uint32_t num;
num = 0;
if (!isdigit(*orig_line)) {
return (-1);
}
while (isdigit(*orig_line)) {
num *= 10;
num += *orig_line - '0';
orig_line++;
}
ADV_SPACE(orig_line);
if (*orig_line != '\0') {
sdp_debug(LOG_ERR, "Garbage at end of integer %s", orig_line);
return(-1);
}
switch (arg) {
case 0:
if (mptr == NULL) return (-1);
mptr->ptime = num;
mptr->ptime_present = TRUE;
break;
case 1:
if (mptr == NULL) return (-1);
mptr->quality = num;
mptr->quality_present = TRUE;
break;
}
return (0);
}
/*
* check_value_list_or_user()
* This will compare string in lptr with items in list. If strncasecmp()
* matches, and the next value after the match in lptr is a space or \0,
* we return the index in list + 1.
* If no entrys are on the list, we'll strdup the value, and store in
* *uservalue
*/
static int check_value_list_or_user (char *lptr,
const char **list,
char **user_value)
{
uint32_t len;
int cnt;
cnt = 1;
while (*list != NULL) {
len = strlen(*list);
if (strncasecmp(lptr, *list, len) == 0) {
return (cnt);
}
cnt++;
list++;
}
*user_value = strdup(lptr);
return(cnt);
}
const char *type_values[] = {
"broadcast", // CONFERENCE_TYPE_BROADCAST
"meeting", // CONFERENCE_TYPE_MEETING
"moderated", // CONFERENCE_TYPE_MODERATED
"test", // CONFERENCE_TYPE_TEST
"H332", // CONFERENCE_TYPE_H332
NULL // CONFERENCE_TYPE_USER
};
static const char *orient_values[] = {
"portrait", // ORIENT_TYPE_PORTRAIT
"landscape",// ORIENT_TYPE_LANDSCAPE
"seascape", // ORIENT_TYPE_SEASCAPE
NULL // ORIENT_TYPE_USER
};
/*
* sdp_decode_parse_a_str()
* parses a=<identifier>:<name>
* Will usually save the value of <name> in a field in the media_desc_t or
* session_desc_t.
*/
static int sdp_decode_parse_a_str (int arg,
char *lptr,
session_desc_t *sptr,
media_desc_t *mptr)
{
switch (arg) {
case 0: // keywds
if (sptr->keywds != NULL) {
sdp_debug(LOG_ERR, "2nd keywds statement");
return (-1);
}
sptr->keywds = strdup(lptr);
break;
case 1: // tool
if (sptr->tool != NULL) {
sdp_debug(LOG_ERR, "2nd tool statement");
return (-1);
}
sptr->tool = strdup(lptr);
break;
case 2: // charset
if (sptr->charset != NULL) {
sdp_debug(LOG_ERR, "2nd charset statement");
return (-1);
}
sptr->charset = strdup(lptr);
break;
case 3: // sdplang
if (mptr != NULL) {
if (mptr->sdplang != NULL) {
sdp_debug(LOG_ERR, "2nd sdplang statement in media");
return (-1);
}
mptr->sdplang = strdup(lptr);
} else {
if (sptr->sdplang != NULL) {
sdp_debug(LOG_ERR, "2nd sdplang statement in session");
return (-1);
}
sptr->sdplang = strdup(lptr);
}
break;
case 4: // lang
if (mptr != NULL) {
if (mptr->lang != NULL) {
sdp_debug(LOG_ERR, "2nd lang statement in media");
return (-1);
}
mptr->lang = strdup(lptr);
} else {
if (sptr->lang != NULL) {
sdp_debug(LOG_ERR, "2nd lang statement in media");
return (-1);
}
sptr->lang = strdup(lptr);
}
break;
case 5: // type
if (sptr->conf_type != 0) {
sdp_debug(LOG_ERR, "2nd conftype statement");
return (-1);
}
sptr->conf_type = check_value_list_or_user(lptr,
type_values,
&sptr->conf_type_user);
break;
case 6: // orient
if (mptr == NULL || mptr->orient_type != 0) {
sdp_debug(LOG_ERR, "2nd orient type statement");
return (-1);
}
mptr->orient_type = check_value_list_or_user(lptr,
orient_values,
&mptr->orient_user_type);
break;
case 7: // control
if (mptr == NULL) {
if (sptr->control_string != NULL) {
sdp_debug(LOG_ERR, "2nd control statement in media");
return (-1);
}
sptr->control_string = strdup(lptr);
} else {
if (mptr->control_string != NULL) {
sdp_debug(LOG_ERR, "2nd control statement in session");
return (-1);
}
mptr->control_string = strdup(lptr);
}
break;
case 8:
if (sptr->etag != NULL) {
sdp_debug(LOG_ERR, "2nd etag statement");
return (-1);
}
sptr->etag = strdup(lptr);
break;
}
return (0);
}
/*
* This structure provides the information needed by the parsing
* engine in sdp_decode_parse_a. This function processes lines of
* the format a=<identifier>[:<options>].
* name - <identifier>
* len - sizeof(identifier) (saves on CPU time)
* have_colon - if a colon is necessary
* remove_spaces_after_colon - if colon is necessary, and we want
* to remove spaces before <option>. Do not use this if other character
* sets may come into play.
* parse_routine - routine to call if keyword matched. Return 0 if successful-
* -1 will save the whole "a=..." string.
* arg - value to pass to parse_routine
*/
static struct {
char *name;
uint32_t len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -