⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp_session.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / IETF RTP/RTSP/SDP sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/ietf_dev.h>#include <gpac/base_coding.h>#ifdef _WIN32_WCE#define RTSP_TRACE		0#else#define RTSP_TRACE		1#endifGF_Err RTSP_UnpackURL(char *sURL, char *Server, u16 *Port, char *Service, Bool *useTCP){	char schema[10], *test, text[1024], *retest;	u32 i, len;	Bool is_ipv6;	if (!sURL) return GF_BAD_PARAM;	strcpy(Server, "");	strcpy(Service, "");	*Port = *useTCP =0;		if (!strchr(sURL, ':')) return GF_BAD_PARAM;	//extract the schema	i = 0;	while (i<=strlen(sURL)) {		if (sURL[i] == ':') goto found;		schema[i] = sURL[i];		i += 1;	}	return GF_BAD_PARAM;found:	schema[i] = 0;	if (stricmp(schema, "rtsp") && stricmp(schema, "rtspu")) return GF_URL_ERROR; 	//check for user/pass - not allowed/*	test = strstr(sURL, "@");	if (test) return GF_NOT_SUPPORTED;*/	test = strstr(sURL, "://");	if (!test) return GF_URL_ERROR;	test += 3;	//check for service	retest = strstr(test, "/");	if (!retest) return GF_URL_ERROR;	if (!stricmp(schema, "rtsp")) *useTCP = 1;	//check for port	retest = strrchr(test, ':');	/*IPV6 address*/	if (retest && strchr(retest, ']')) retest = NULL;	if (retest && strstr(retest, "/")) {		retest += 1;		i=0;		while (i<strlen(retest)) {			if (retest[i] == '/') break;			text[i] = retest[i];			i += 1;		}		text[i] = 0;		*Port = atoi(text);	}	//get the server name	is_ipv6 = 0;	len = strlen(test);	i=0;	while (i<len) {		if (test[i]=='[') is_ipv6 = 1;		else if (test[i]==']') is_ipv6 = 0;		if ( (test[i] == '/') || (!is_ipv6 && (test[i] == ':')) ) break;		text[i] = test[i];		i += 1;	}	text[i] = 0;	strcpy(Server, text);	while (test[i] != '/') i += 1;	strcpy(Service, test+i+1);	return GF_OK;}//create a new GF_RTSPSession from URL - DO NOT USE WITH SDPGF_EXPORTGF_RTSPSession *gf_rtsp_session_new(char *sURL, u16 DefaultPort){	GF_RTSPSession *sess;	char server[1024], service[1024];	GF_Err e;	u16 Port;	Bool UseTCP;		if (!sURL) return NULL;	e = RTSP_UnpackURL(sURL, server, &Port, service, &UseTCP);	if (e) return NULL;	GF_SAFEALLOC(sess, GF_RTSPSession);	sess->ConnectionType = UseTCP ? GF_SOCK_TYPE_TCP : GF_SOCK_TYPE_UDP;	if (Port) sess->Port = Port;	else if (DefaultPort) sess->Port = DefaultPort;	else sess->Port = 554;	//HTTP tunnel	if (sess->Port == 80) {		sess->ConnectionType = GF_SOCK_TYPE_TCP;		sess->HasTunnel = 1;	}		sess->Server = strdup(server);	sess->Service = strdup(service);	sess->mx = gf_mx_new();	sess->TCPChannels = gf_list_new();	gf_rtsp_session_reset(sess, 0);	return sess;}GF_EXPORTvoid gf_rtsp_reset_aggregation(GF_RTSPSession *sess){	if (!sess) return;		gf_mx_p(sess->mx);	if (sess->RTSP_State == GF_RTSP_STATE_WAIT_FOR_CONTROL) {		strcpy(sess->RTSPLastRequest, "RESET");		//skip all we haven't recieved		sess->CSeq += sess->NbPending;		sess->NbPending = 0;	}	sess->RTSP_State = GF_RTSP_STATE_INIT;	gf_mx_v(sess->mx);}void RTSP_AcknowledgeError(GF_RTSPSession *sess){}void RemoveTCPChannels(GF_RTSPSession *sess){	GF_TCPChan *ch;	while (gf_list_count(sess->TCPChannels)) {		ch = (GF_TCPChan*)gf_list_get(sess->TCPChannels, 0);		free(ch);		gf_list_rem(sess->TCPChannels, 0);	}}GF_EXPORTvoid gf_rtsp_session_reset(GF_RTSPSession *sess, Bool ResetConnection){	gf_mx_p(sess->mx);	sess->last_session_id = NULL;	sess->NeedConnection = 1;	if (ResetConnection) {		if (sess->connection) gf_sk_del(sess->connection);		sess->connection = NULL;		if (sess->http) {			gf_sk_del(sess->http);			sess->http = NULL;		}	}		sess->RTSP_State = GF_RTSP_STATE_INIT;//	sess->CSeq = sess->NbPending = 0;	sess->InterID = (u8) -1;	sess->pck_start = sess->payloadSize = 0;	sess->CurrentPos = sess->CurrentSize = 0;	strcpy(sess->RTSPLastRequest, "");	RemoveTCPChannels(sess);	gf_mx_v(sess->mx);}GF_EXPORTvoid gf_rtsp_session_del(GF_RTSPSession *sess){	if (!sess) return;	gf_rtsp_session_reset(sess, 0);	if (sess->connection) gf_sk_del(sess->connection);	if (sess->http) gf_sk_del(sess->http);	if (sess->Server) free(sess->Server);	if (sess->Service) free(sess->Service);	gf_list_del(sess->TCPChannels);	if (sess->rtsp_pck_buf) free(sess->rtsp_pck_buf);	gf_mx_del(sess->mx);	free(sess);}GF_EXPORTu32 gf_rtsp_get_session_state(GF_RTSPSession *sess){	u32 state;	if (!sess) return GF_RTSP_STATE_INVALIDATED;		gf_mx_p(sess->mx);	state = sess->RTSP_State;	gf_mx_v(sess->mx);	return state;}GF_EXPORTchar *gf_rtsp_get_last_request(GF_RTSPSession *sess){	char *ret;	if (!sess) return NULL;	gf_mx_p(sess->mx);	ret = sess->RTSPLastRequest;	gf_mx_v(sess->mx);	return ret;}//check whether the url contains server and service name//no thread protection as this is const throughout the sessionGF_EXPORTu32 gf_rtsp_is_my_session(GF_RTSPSession *sess, char *url){	if (!sess) return 0;	if (!strstr(url, sess->Server)) return 0;	//same url or sub-url	if (strstr(url, sess->Service)) return 1;	return 0;}GF_EXPORTconst char *gf_rtsp_get_last_session_id(GF_RTSPSession *sess){	if (!sess) return NULL;	return sess->last_session_id;}GF_EXPORTchar *gf_rtsp_get_server_name(GF_RTSPSession *sess){	if (!sess) return NULL;	return sess->Server;}GF_EXPORTchar *gf_rtsp_get_service_name(GF_RTSPSession *sess){	if (!sess) return NULL;	return sess->Service;}GF_EXPORTu16 gf_rtsp_get_session_port(GF_RTSPSession *sess){	return (sess ? sess->Port : 0);}GF_Err gf_rtsp_check_connection(GF_RTSPSession *sess){	GF_Err e;	//active, return	if (!sess->NeedConnection) return GF_OK;	//socket is destroyed, recreate	if (!sess->connection) {		sess->connection = gf_sk_new(sess->ConnectionType);		if (!sess->connection) return GF_OUT_OF_MEM;	}	//the session is down, reconnect	e = gf_sk_connect(sess->connection, sess->Server, sess->Port);	if (e) return e;	if (sess->SockBufferSize) gf_sk_set_buffer_size(sess->connection, 0, sess->SockBufferSize);	if (!sess->http && sess->HasTunnel) {		e = gf_rtsp_http_tunnel_start(sess, "toto is the king of RTSP");		if (e) return e;	}	sess->NeedConnection = 0;	return GF_OK;}GF_Err gf_rtsp_send_data(GF_RTSPSession *sess, char *buffer, u32 Size){	GF_Err e;	u32 Size64;	e = gf_rtsp_check_connection(sess);	if (e) return e;	//RTSP requests on HTTP are base 64 encoded	if (sess->HasTunnel) {		char buf64[3000];		Size64 = gf_base64_encode(buffer, Size, buf64, 3000);		buf64[Size64] = 0;		//send on http connection		return gf_sk_send_wait(sess->http, buf64, Size64, 30);	} else {		return gf_sk_send(sess->connection, buffer, Size);	}}static GF_TCPChan *GetTCPChannel(GF_RTSPSession *sess, u8 rtpID, u8 rtcpID, Bool RemoveIt){	GF_TCPChan *ptr;	u32 i, count = gf_list_count(sess->TCPChannels);	for (i=0; i<count; i++) {		ptr = (GF_TCPChan *)gf_list_get(sess->TCPChannels, i);		if (ptr->rtpID == rtpID) goto exit;;		if (ptr->rtcpID == rtcpID) goto exit;	}	return NULL;exit:	if (RemoveIt) gf_list_rem(sess->TCPChannels, i);	return ptr;}GF_Err gf_rtsp_set_deinterleave(GF_RTSPSession *sess){	GF_TCPChan *ch;	Bool IsRTCP;	u8 InterID;	u16 paySize;	u32 res, Size;	char *buffer;	if (!sess) return GF_SERVICE_ERROR;	Size = sess->CurrentSize - sess->CurrentPos;	buffer = sess->TCPBuffer + sess->CurrentPos;	if (!Size) return GF_IP_NETWORK_EMPTY;	//we do not work with just a header -> force a refill	if (Size <= 4) return gf_rtsp_refill_buffer(sess);	//break if we get RTSP response on the wire	if (!strncmp(buffer, "RTSP", 4)) 		return GF_IP_NETWORK_EMPTY;	//new packet	if (!sess->pck_start && (buffer[0] == '$')) {		InterID = buffer[1];		paySize = ((buffer[2] << 8) & 0xFF00) | (buffer[3] & 0xFF);		/*this may be NULL (data fetched after a teardown) - resync and return*/		ch = GetTCPChannel(sess, InterID, InterID, 0);		/*then check wether this is a full packet or a split*/		if (paySize <= Size-4) {			if (ch) {				IsRTCP = (ch->rtcpID == InterID);				sess->RTSP_SignalData(sess, ch->ch_ptr, buffer+4, paySize, IsRTCP);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -