📄 rtsp.c
字号:
/** Parse RTSP-specific header fields.* This file is same as rtspd/rtsp.c except for the short form table.*/#include "sysdep.h"#include <stdlib.h> /* atoi(), atof(), strtol() */#include <string.h> /* strchr() */#include <stdio.h> /* sscanf() */#include <time.h> /* mktime() */#include <sys/time.h> /* gettimeofday() */#include <timegm.h> /* timegm() */#include "afi.h"#include "rtsp.h"#include "shortform.h"#include "strdupn.h"/** RTSP_CSeq()* RTSP sequence number.*/int RTSP_CSeq(parser_t *P){ parser_header_t *h = RFC822_Header(P->headers, "CSeq"); return h ? atoi(RFC822_Attribute(h, 0, 0)) : -1;} /* RTSP_CSeq *//** RTSP_MaxSize()* RTSP MaxSize header. return (unsigned long) -1 if* absent.*/unsigned long RTSP_MaxSize(parser_t *P){ parser_header_t *h = RFC822_Header(P->headers, "MaxSize"); return h ? atol(RFC822_Attribute(h, 0, 0)) : -1;} /* RTSP_CSeq *//* * RTSP_Range() * Range: clock= npt=; time= * Return range description. Does not support SMPTE (yet). */rtsp_range_t RTSP_Range(parser_t *P){ parser_header_t *h = RFC822_Header(P->headers, "Range"); rtsp_range_t r; char *dash; char *v; r.effective = -1.; r.type = -1; r.begin = -1.; r.end = -1.; if (h) { v = RFC822_Attribute(h, 0, "time"); if (v) r.effective = strtoutc(v); if ((v = RFC822_Attribute(h, 0, 0))) { if (!strncmp(v, "clock=", strlen("clock=")) ) { r.type = R_clock; r.begin = strtoutc(v + strlen("clock=")); if ((dash = strchr(v, '-'))) r.end = strtoutc(dash+1); } else if (!strncmp(v,"npt=", strlen("npt="))) { r.type = R_npt; r.begin = strtonpt(v + strlen("npt=")); if ((dash = strchr(v, '-'))) { if (*(dash+1) == '-') { r.end = -1.0; /* XXX to interoperate with quicktime */ } else { r.end = strtonpt(dash+1); if ( r.end == 0 ) { r.end = -1.0; /* to the end */ } } } } else if (!strncmp(v, "smpte=", strlen("smpte="))) { r.type = R_smpte; } else { } } } if (r.effective < 0) { struct timeval tv; gettimeofday(&tv, 0); r.effective = tv.tv_sec + tv.tv_usec / 1e6; } return r;} /* RTSP_Range *//* * RTSP_Scale(): * Scale: 5.1 * Return play rate description. */float RTSP_Scale(parser_t *p){ parser_header_t *h = RFC822_Header(p->headers, "Scale"); float f = 1.0; if (h) { f = atof(h->elements->value); } return f;} /* RTSP_Scale *//* * RTSP_Subject(): XXX there is no Subject: header defined * in RTSP RFC. This is a non-standard feature. * Subject: Any text... * Returns the subject string. */const char * RTSP_Subject(parser_t *p){ parser_header_t *h = RFC822_Header(p->headers, "Subject"); if (h) { return h->elements->value; } else { return "No subject in RTSP message"; }} /* RTSP_Scale *//* * RTSP_Speed(): * Speed: 5.1 * Return delivery rate. */float RTSP_Speed(parser_t *p){ parser_header_t *h = RFC822_Header(p->headers, "Speed"); float f = 1.0; if (h) { f = atof(h->elements->value); } return f;} /* RTSP_Scale *//* * RTSP_Session: * Session: some string ;timeout=T * Return session identifier. */rtsp_session_t RTSP_Session(parser_t *p){ parser_header_t *h = RFC822_Header(p->headers, "Session"); rtsp_session_t s = {0, 0}; char *v; if (h) { s.id = h->elements->value; v = RFC822_Attribute(h, 0, "timeout"); if (v) s.timeout = atoi(v); } return s;} /* RTSP_Session *//** RTSP_Timestamp():* Timestamp: 38383.3 1.03*/rtsp_timestamp_t RTSP_Timestamp(parser_t *P){ parser_header_t *h = RFC822_Header(P->headers, "Timestamp"); rtsp_timestamp_t t = {0,0}; char *v; if (h && (v = RFC822_Attribute(h, 0, 0))) { sscanf(v, "%lf %lf", &t.timestamp, &t.delay); } return t;} /* RTSP_Timestamp *//* * RTSP_Transport(): * Transport: RTP/AVP;multicast;compressed;ttl=127;mode="PLAY" * Returns a transport description. */rtsp_transport_t RTSP_Transport(parser_t *p){ parser_header_t *h = RFC822_Header(p->headers, "Transport"); char *v; rtsp_transport_t r; char *method; r.protocol = P_RTP; r.profile = Pr_AVP; r.port[0] = 3458; r.port[1] = 3459; r.client_port[0] = r.port[0]; r.client_port[1] = r.port[1]; r.server_port[0] = r.port[0]; r.server_port[1] = r.port[1]; r.ttl = 0; r.layers = 1; r.ssrc = 0; r.multicast = B_FALSE; r.interleaved = 0; r.compressed = 0; r.mode = 0; method = HTTP_Method(p); if (method != NULL ) { if (!strcmp(method,"RECORD")) r.mode = T_RECORD; /*07/24/99 AM */ if (!strcmp(method,"PLAY")) r.mode = T_PLAY; } r.append = 0; r.destination4.s_addr = INADDR_ANY; memset(&r.destination6, 0, sizeof(struct in6_addr)); r.af = AF_UNSPEC; /* default to nothing for now */ r.transport = T_UDP; if (h) {#if 1 parser_parameter_t *p = NULL; if ( (v = RFC822_Attribute(h,0,0))) { if ((!strncasecmp(v, "rtp/avp/tcp", strlen("rtp/avp/tcp"))) ){ r.transport = T_TCP; r.profile = Pr_AVP; r.protocol = P_RTP; } else if ((!strncasecmp(v, "rtp/avp",strlen("rtp/avp"))) ){ r.transport = T_UDP; r.profile = Pr_AVP; r.protocol = P_RTP; } else { r.transport = T_UDP; // default assumed to be UDP r.profile = Pr_AVP; r.protocol = P_RTP; } RFC822_ParseHeader(v,0,NULL,HT_standard,&p); v = RFC822_Attribute1(p, "port"); if (v) sscanf(v, "%u-%u", &r.port[0], &r.port[1]); v = RFC822_Attribute1(p, "client_port"); if (v) { sscanf(v, "%u-%u", &r.client_port[0], &r.client_port[1]); r.client_port[1] = r.client_port[0] + 1; /* XXX remove this line */ } v = RFC822_Attribute1(p, "server_port"); if (v) sscanf(v, "%u-%u", &r.server_port[0], &r.server_port[1]); v = RFC822_Attribute1(p, "ssrc"); if (v) r.ssrc = strtol(v,NULL,16); v = RFC822_Attribute1(p, "ttl"); if (v) r.ttl = atoi(v); v = RFC822_Attribute1(p, "interleaved"); if (v) r.interleaved = atoi(v); v = RFC822_Attribute1(p, "compressed"); if (v) r.compressed = B_TRUE; v = RFC822_Attribute1(p, "destination"); if (v) { struct sockaddr_storage sin; memset(&sin, 0, sizeof(sin)); if (AFIGetAddrByName(&sin, v) == 0) { r.af = sin.ss_family; if (sin.ss_family == AF_INET) { struct sockaddr_in *p4 = (struct sockaddr_in*)&sin; r.destination4.s_addr = p4->sin_addr.s_addr; } else { struct sockaddr_in6 *p6 = (struct sockaddr_in6*)&sin; memcpy(&r.destination6, &p6->sin6_addr, sizeof(struct in6_addr)); } } } v = RFC822_Attribute1(p, "multicast"); if (v) r.multicast = B_TRUE; if ( (v = RFC822_Attribute1(p, "rtp/avp")) ){ r.transport = T_UDP; r.profile = Pr_AVP; r.protocol = P_RTP; } else if ( (v = RFC822_Attribute1(p, "rtp/avp/tcp")) ){ r.transport = T_TCP; r.profile = Pr_AVP; r.protocol = P_RTP; } else { r.transport = T_UDP; // default assumed to be UDP r.profile = Pr_AVP; r.protocol = P_RTP; } v = RFC822_Attribute1(p, "mode"); if (v) { if (!strcasecmp(v, "PLAY")) r.mode |= T_PLAY; if (!strcasecmp(v, "RECORD")) r.mode |= T_RECORD; } RFC822_ParameterFree(p); }#else /* * Following lines are removed and replaced by above lines */ v = RFC822_Attribute(h, 0, "port"); if (v) sscanf(v, "%u-%u", &r.port[0], &r.port[1]); v = RFC822_Attribute(h, 0, "client_port"); if (v) sscanf(v, "%u-%u", &r.client_port[0], &r.client_port[1]); v = RFC822_Attribute(h, 0, "server_port"); if (v) sscanf(v, "%u-%u", &r.server_port[0], &r.server_port[1]); v = RFC822_Attribute(h, 0, "ssrc"); if (v) r.ssrc = strtol(v,NULL,16); v = RFC822_Attribute(h, 0, "ttl"); if (v) r.ttl = atoi(v); v = RFC822_Attribute(h, 0, "interleaved"); if (v) r.interleaved = atoi(v); v = RFC822_Attribute(h, 0, "compressed"); if (v) r.compressed = B_TRUE; /* XXX: change this part to use AFIGetAddrByName as defined * in the #if 1 part above. */ v = RFC822_Attribute(h, 0, "destination"); if (v) r.destination = host2ip(v); v = RFC822_Attribute(h, 0, "multicast"); if (v) r.multicast = B_TRUE; if ( (v = RFC822_Attribute(h, 0, "rtp/avp")) ){ r.transport = T_UDP; r.profile = Pr_AVP; r.protocol = P_RTP; } else if ( (v = RFC822_Attribute(h, 0, "rtp/avp/tcp")) ){ r.transport = T_TCP; r.profile = Pr_AVP; r.protocol = P_RTP; } else { r.transport = T_UDP; // default assumed to be UDP r.profile = Pr_AVP; r.protocol = P_RTP; } v = RFC822_Attribute(h, 0, "mode"); if (v) { if (strstr(v, "PLAY")) r.mode |= T_PLAY; if (strstr(v, "RECORD")) r.mode |= T_RECORD; }#endif } free_valid(method); return r;} /* RTSP_Transport *//** strtonpt()* 124.45 or 12:05:04.3* Parse an NPT timestamp.*/double strtonpt(char *npt){ int hh = 0, mm = 0, ss = 0; int n; /* number of elements */ char *decimal; double t; /* converted time */ if (strchr(npt, ':')) { n = sscanf(npt, "%d:%d:%d", &hh, &mm, &ss); t = hh*3600 + mm*60 + ss; } else { n = sscanf(npt, "%d", &ss); t = ss; } if ((decimal = strchr(npt, '.'))) { t += atof(decimal); } return t;} /* strtonpt *//** strtosmpte()* hh:mm:ss.frame*/double strtosmpte(char *smpte){ return 0.;} /* strtosmpte *//** strtoutc()* yyyymmddThhmmss.fZ (e.g., 19961108T143720.25Z)*/double strtoutc(char *utc){ double t; char *decimal; /* position of decimal point */ struct tm tm; memset(&tm, 0, sizeof(tm)); sscanf(utc, "%4d%2d%2dT%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); tm.tm_year -= 1900; /* tm_year is years since 1900 */ tm.tm_mon -= 1; /* tm_mon is [0,11]! */ t = timegm(&tm); /* Add fractions of a second. */ if ((decimal = strchr(utc, '.'))) t += atof(decimal); return t;} /* strtoutc *//** utctostr()* Convert time to UTC string format.*/void utctostr(double utc, char *buffer){ struct tm tm; time_t clock = (time_t)utc; gmtime_r(&clock, &tm); sprintf(buffer, "%04d%02d%02dT%02d%02d%02dZ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);} /* utctostr *//** npttostr()* Convert time to NPT format (as decimal, not hh:mm:ss). */void npttostr(double npt, char *buffer){ sprintf(buffer, "%.4f", npt);} /* npttostr *//** smptetostr()* Convert time to SMPTE format.*/void smptetostr(double smpte, char *buffer){} /* smptetostr */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -