初始化实际就是创建rtmp对象实例,然后初始化各个成员。
// 创建rtmp对象,设置rtmp实例的属性voidRTMP_Init(RTMP *r){#ifdef CRYPTO if (!RTMP_TLS_ctx) RTMP_TLS_Init();#endif memset(r, 0, sizeof(RTMP)); r->m_sb.sb_socket = -1; r->m_inChunkSize = RTMP_DEFAULT_CHUNKSIZE; r->m_outChunkSize = RTMP_DEFAULT_CHUNKSIZE; r->m_nBufferMS = 30000; r->m_nClientBW = 2500000; r->m_nClientBW2 = 2; r->m_nServerBW = 2500000; r->m_fAudioCodecs = 3191.0; r->m_fVideoCodecs = 252.0; r->Link.timeout = 30; r->Link.swfAge = 30; r->Link.CombineConnectPacket = TRUE; r->Link.ConnectPacket = FALSE;}URL解析
URL解析的目的是把URL中的各个成分提取出来,为接下来连接的建立做准备。
以 rtmp://live.hkstv.hk.lxdns.com/live/hks为例子,它经过解析之后,就可以得到下面各个部分:
协议:rtmp host:live.hkstv.hk.lxdns.com/live/hks path:hks application:live/hks
/*** 解析rtmp的URL*/int RTMP_ParseURL(const char *url, int *PRotocol, AVal *host, unsigned int *port, AVal *playpath, AVal *app){ char *p, *end, *col, *ques, *slash; RTMP_Log(RTMP_LOGDEBUG, "Parsing..."); // 设置默认的协议:rtmp *protocol = RTMP_PROTOCOL_RTMP; *port = 0; playpath->av_len = 0; playpath->av_val = NULL; app->av_len = 0; app->av_val = NULL; /* Old School Parsing */ /* look for usual :// pattern */ p = strstr(url, "://"); if (!p) { RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!"); return FALSE; } { int len = (int)(p - url); // 解析协议头 /* ** 支持的协议有: ** rtmp ** rtmpe ** rtmpt ** rtmps ** rtmpte ** rtmpts ** rtmfp */ if (len == 4 && strncasecmp(url, "rtmp", 4) == 0) *protocol = RTMP_PROTOCOL_RTMP; else if (len == 5 && strncasecmp(url, "rtmpt", 5) == 0) *protocol = RTMP_PROTOCOL_RTMPT; else if (len == 5 && strncasecmp(url, "rtmps", 5) == 0) *protocol = RTMP_PROTOCOL_RTMPS; else if (len == 5 && strncasecmp(url, "rtmpe", 5) == 0) *protocol = RTMP_PROTOCOL_RTMPE; else if (len == 5 && strncasecmp(url, "rtmfp", 5) == 0) *protocol = RTMP_PROTOCOL_RTMFP; else if (len == 6 && strncasecmp(url, "rtmpte", 6) == 0) *protocol = RTMP_PROTOCOL_RTMPTE; else if (len == 6 && strncasecmp(url, "rtmpts", 6) == 0) *protocol = RTMP_PROTOCOL_RTMPTS; else { RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!/n"); goto parsehost; } } RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol);parsehost: /* let's get the hostname */ p += 3; /* check for sudden death */ if (*p == 0) { RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!"); return FALSE; } end = p + strlen(p); col = strchr(p, ':'); ques = strchr(p, '?'); slash = strchr(p, '/'); // 解析主机名 { int hostlen; if (slash) hostlen = slash - p; else hostlen = end - p; if (col && col - p < hostlen) hostlen = col - p; if (hostlen < 256) { host->av_val = p; host->av_len = hostlen; RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val); } else { RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!"); } p += hostlen; } // 解析端口号 /* get the port number if available */ if (*p == ':') { unsigned int p2; p++; p2 = atoi(p); if (p2 > 65535) { RTMP_Log(RTMP_LOGWARNING, "Invalid port number!"); } else { *port = p2; } } if (!slash) { RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!"); return TRUE; } p = slash + 1; // 解析app { /* parse application * * rtmp://host[:port]/app[/appinstance][/...] * application = app[/appinstance] */ char *slash2, *slash3 = NULL; int applen, appnamelen; slash2 = strchr(p, '/'); if (slash2) slash3 = strchr(slash2 + 1, '/'); applen = end - p; /* ondemand, pass all parameters as app */ appnamelen = applen; /* ondemand length */ if (ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ appnamelen = ques - p; } else if (strncmp(p, "ondemand/", 9) == 0) { /* app = ondemand/foobar, only pass app=ondemand */ applen = 8; appnamelen = 8; } else { /* app!=ondemand, so app is app[/appinstance] */ if (slash3) appnamelen = slash3 - p; else if (slash2) appnamelen = slash2 - p; applen = appnamelen; } app->av_val = p; app->av_len = applen; RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p); p += appnamelen; } if (*p == '/') p++; // 解析path if (end - p) { AVal av = { p, end - p }; RTMP_ParsePlaypath(&av, playpath); } return TRUE;}
新闻热点
疑难解答