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

📄 rtp_session.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / RTP input module * *  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 "rtp_in.h"void RP_SendFailure(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e){	char sMsg[1000];	sprintf(sMsg, "Cannot send %s", com->method);	gf_term_on_message(sess->owner->service, e, sMsg);}Bool RP_ProcessResponse(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e){	if (!strcmp(com->method, GF_RTSP_DESCRIBE)) 		return RP_ProcessDescribe(sess, com, e);	else if (!strcmp(com->method, GF_RTSP_SETUP)) 		RP_ProcessSetup(sess, com, e);	else if (!strcmp(com->method, GF_RTSP_TEARDOWN)) 		RP_ProcessTeardown(sess, com, e);	else if (!strcmp(com->method, GF_RTSP_PLAY) || !strcmp(com->method, GF_RTSP_PAUSE)) 		RP_ProcessUserCommand(sess, com, e);	return GF_OK;}/*access to command list is protected bymutex, BUT ONLY ACCESS - this way we're sure that command queueingfrom app will not deadlock if we're waiting for the app to release any mutex (don't forget play request may come on stream N while we're processing stream P setup)*/static GF_RTSPCommand *RP_GetCommand(RTSPSession *sess){	GF_RTSPCommand *com;	gf_mx_p(sess->owner->mx);	com = (GF_RTSPCommand *)gf_list_get(sess->rtsp_commands, 0);	gf_mx_v(sess->owner->mx);	return com;}static void RP_RemoveCommand(RTSPSession *sess){	gf_mx_p(sess->owner->mx);	gf_list_rem(sess->rtsp_commands, 0);	gf_mx_v(sess->owner->mx);}void RP_ProcessCommands(RTSPSession *sess){	GF_RTSPCommand *com;	GF_Err e;	u32 time;	com = RP_GetCommand(sess);	/*if asked or command to send, flushout TCP - TODO: check what's going on with ANNOUNCE*/	if ((com && !(sess->flags & RTSP_WAIT_REPLY) ) || (sess->flags & RTSP_TCP_FLUSH) ) {		while (1) {			e = gf_rtsp_session_read(sess->session);			if (e) break;		}		sess->flags &= ~RTSP_TCP_FLUSH;	}	/*handle response or announce*/	if ( (com && (sess->flags & RTSP_WAIT_REPLY) ) /*|| (!com && sess->owner->handle_announce)*/) {		e = gf_rtsp_get_response(sess->session, sess->rtsp_rsp);		if (e!= GF_IP_NETWORK_EMPTY) {			e = RP_ProcessResponse(sess, com, e);			/*this is a service connect error -> plugin may be discarded */			if (e!=GF_OK) {				RP_RemoveCommand(sess);				gf_rtsp_command_del(com);				gf_term_on_connect(sess->owner->service, NULL, e);				return;			}			RP_RemoveCommand(sess);			gf_rtsp_command_del(com);			sess->flags &= ~RTSP_WAIT_REPLY;			sess->command_time = 0;		} else {			/*evaluate timeout*/			time = gf_sys_clock() - sess->command_time;			/*don't waste time waiting for teardown ACK, half a sec is enough. If server is not replying			in time it is likely to never reply (happens with RTP over RTSP) -> kill session 			and create new one*/			if (!strcmp(com->method, GF_RTSP_TEARDOWN) && (time>=500) ) time = sess->owner->time_out;			//signal what's going on			if (time >= sess->owner->time_out) {				if (!strcmp(com->method, GF_RTSP_TEARDOWN)) gf_rtsp_session_reset(sess->session, 1);				RP_ProcessResponse(sess, com, GF_IP_NETWORK_FAILURE);				RP_RemoveCommand(sess);				gf_rtsp_command_del(com);				sess->flags &= ~RTSP_WAIT_REPLY;				sess->command_time = 0;				gf_rtsp_reset_aggregation(sess->session);			}		}		return;	}	if (!com) return;	/*send command - check RTSP session state first*/	switch (gf_rtsp_get_session_state(sess->session)) {	case GF_RTSP_STATE_WAITING:	case GF_RTSP_STATE_WAIT_FOR_CONTROL:		return;	case GF_RTSP_STATE_INVALIDATED:		RP_SendFailure(sess, com, GF_IP_NETWORK_FAILURE);		RP_RemoveCommand(sess);		gf_rtsp_command_del(com);		sess->flags &= ~RTSP_WAIT_REPLY;		sess->command_time = 0;		return;	}	/*process*/	com->User_Agent = RTSP_CLIENTNAME;	com->Accept_Language = RTSP_LANGUAGE;	/*if no session assigned and a session ID is valid, use it*/	if ((sess->owner->stream_control_type!=RTSP_CONTROL_INDEPENDENT) && sess->session_id && !com->Session)		com->Session = sess->session_id;	e = GF_OK;	/*preprocess describe before sending (always the ESD url thing)*/	if (!strcmp(com->method, GF_RTSP_DESCRIBE)) {		com->Session = NULL;		if (!RP_PreprocessDescribe(sess, com)) {			e = GF_BAD_PARAM;			goto exit;		}	}	/*preprocess play/stop/pause before sending (aggregation)*/	if (!strcmp(com->method, GF_RTSP_PLAY) 		|| !strcmp(com->method, GF_RTSP_PAUSE)		|| !strcmp(com->method, GF_RTSP_TEARDOWN)) {		//command is skipped		if (!RP_PreprocessUserCom(sess, com)) {			e = GF_BAD_PARAM;			goto exit;		}	}	e = gf_rtsp_send_command(sess->session, com);	if (e) {		RP_SendFailure(sess, com, e);		RP_ProcessResponse(sess, com, e);	} else {		sess->command_time = gf_sys_clock();		sess->flags |= RTSP_WAIT_REPLY;	}exit:	/*reset static strings*/	com->User_Agent = NULL;	com->Accept_Language = NULL;	com->Session = NULL;	/*remove command*/	if (e) {		RP_RemoveCommand(sess);		gf_rtsp_command_del(com);		sess->flags &= ~RTSP_WAIT_REPLY;		sess->command_time = 0;	}}/*locate channel - if requested remove from session*/RTPStream *RP_FindChannel(RTPClient *rtp, LPNETCHANNEL ch, u32 ES_ID, char *es_control, Bool remove_stream){	u32 i=0;	RTPStream *st;	while ((st = (RTPStream *)gf_list_enum(rtp->channels, &i))) {		if (ch && (st->channel==ch)) goto found;		if (ES_ID && (st->ES_ID==ES_ID)) goto found;		if (es_control && st->control) {			char *ctrl_start = strstr(es_control, st->control);			if (ctrl_start && !strcmp(ctrl_start, st->control)) goto found;		}	}	return NULL;found:	if (remove_stream) gf_list_rem(rtp->channels, i-1);	return st;}/*locate session by control*/RTSPSession *RP_CheckSession(RTPClient *rtp, char *control){	u32 i;	RTSPSession *sess;	if (!control) return NULL;	if (!strcmp(control, "*")) control = (char *) gf_term_get_service_url(rtp->service);	i=0;	while ( (sess = (RTSPSession *)gf_list_enum(rtp->sessions, &i)) ) {		if (gf_rtsp_is_my_session(sess->session, control)) return sess;	}	return NULL;}RTSPSession *RP_NewSession(RTPClient *rtp, char *session_control){	char *szCtrl, *szExt;	RTSPSession *tmp;	GF_RTSPSession *rtsp;	/*little fix: some servers don't understand DESCRIBE URL/trackID=, so remove the trackID...*/	szCtrl = strdup(session_control);	szExt = strrchr(szCtrl, '.');	if (szExt) {		szExt = strchr(szExt, '/');		if (szExt) {			if (!strnicmp(szExt+1, "trackID=", 8) || !strnicmp(szExt+1, "ESID=", 5) || !strnicmp(szExt+1, "ES_ID=", 6)) szExt[0] = 0;		}	}	rtsp = gf_rtsp_session_new(szCtrl, rtp->default_port);	free(szCtrl);	if (!rtsp) return NULL;	GF_SAFEALLOC(tmp, RTSPSession);	tmp->owner = rtp;	tmp->session = rtsp;	if (rtp->transport_mode) {		gf_rtsp_set_buffer_size(rtsp, RTSP_TCP_BUFFER_SIZE);	} else {		gf_rtsp_set_buffer_size(rtsp, RTSP_BUFFER_SIZE);	}	tmp->rtsp_commands = gf_list_new();	tmp->rtsp_rsp = gf_rtsp_response_new();		gf_list_add(rtp->sessions, tmp);	return tmp;}GF_Err RP_AddStream(RTPClient *rtp, RTPStream *stream, char *session_control){	Bool has_aggregated_control;	char *service_name, *ctrl;	RTSPSession *in_session = RP_CheckSession(rtp, session_control);	has_aggregated_control = 0;	if (session_control) {		//if (!strcmp(session_control, "*")) session_control = NULL;		if (session_control) has_aggregated_control = 1;	}	/*regular setup in an established session (RTSP DESCRIBE)*/	if (in_session) {		in_session->flags |= RTSP_AGG_CONTROL;		stream->rtsp = in_session;		gf_list_add(rtp->channels, stream);		return GF_OK;	}	/*setup through SDP with control - assume this is RTSP and try to create a session*/	if (stream->control) {		/*stream control is relative to main session*/		if (strnicmp(stream->control, "rtsp://", 7) && strnicmp(stream->control, "rtspu://", 7)) {			/*locate session by control - if no control was provided for the session, use default			session*/			if (!in_session) in_session = RP_CheckSession(rtp, session_control ? session_control : "*");			/*none found, try to create one*/			if (!in_session) in_session = RP_NewSession(rtp, session_control);			/*cannot add an RTSP session for this channel, check if multicast*///			if (!in_session && gf_rtp_is_unicast(stream->rtp_ch) ) return GF_SERVICE_ERROR;		}		/*stream control is absolute*/		else {			in_session = RP_CheckSession(rtp, stream->control);			if (!in_session) in_session = RP_CheckSession(rtp, session_control);			if (!in_session) {				if (session_control && strstr(stream->control, session_control))					in_session = RP_NewSession(rtp, session_control);				else					in_session = RP_NewSession(rtp, stream->control);				if (!in_session) return GF_SERVICE_ERROR;			}			/*remove session control part from channel control*/			service_name = gf_rtsp_get_service_name(in_session->session);			ctrl = strstr(stream->control, service_name);			if (ctrl && (strlen(ctrl) != strlen(service_name)) ) {				ctrl += strlen(service_name) + 1;				service_name = strdup(ctrl);				free(stream->control);				stream->control = service_name;			}		}	}	/*no control specified, assume this is multicast*/	else {		in_session = NULL;	}	if (in_session) {		in_session->flags |= RTSP_AGG_CONTROL;	} else if (stream->control) {		free(stream->control);		stream->control = NULL;	}	stream->rtsp = in_session;	gf_list_add(rtp->channels, stream);	return GF_OK;}void RP_RemoveStream(RTPClient *rtp, RTPStream *ch){	u32 i=0;	RTPStream *st;	gf_mx_p(rtp->mx);	while ((st = (RTPStream *)gf_list_enum(rtp->channels, &i))) {		if (st == ch) {			gf_list_rem(rtp->channels, i-1);			break;		}	}	gf_mx_v(rtp->mx);}void RP_ResetSession(RTSPSession *sess, GF_Err e){	GF_RTSPCommand *com;	u32 first = 1;	//destroy command list	while (gf_list_count(sess->rtsp_commands)) {		com = (GF_RTSPCommand *)gf_list_get(sess->rtsp_commands, 0);		gf_list_rem(sess->rtsp_commands, 0);		//this destroys stacks if any//		RP_SendFailure(sess, com, first ? e : GF_OK);		gf_rtsp_command_del(com);		first = 0;	}	/*reset session state*/		gf_rtsp_session_reset(sess->session, 1);	sess->flags &= ~RTSP_WAIT_REPLY;}void RP_DelSession(RTSPSession *sess){	RP_ResetSession(sess, GF_OK);	gf_list_del(sess->rtsp_commands);	gf_rtsp_response_del(sess->rtsp_rsp);	gf_rtsp_session_del(sess->session);	if (sess->control) free(sess->control);	if (sess->session_id) free(sess->session_id);	free(sess);}

⌨️ 快捷键说明

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