首页 > 学院 > 开发设计 > 正文

RTMP学习(八)rtmpdump源码阅读(3)初始化与URL解析

2019-11-06 08:52:07
字体:
来源:转载
供稿:网友

初始化与URL解析

初始化

    初始化实际就是创建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;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表