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

📄 rtp_signaling.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
		return 0;	}	assert(ch->rtsp == sess);	assert(ch->channel==ch_ctrl->com.base.on_channel);	if (sess->owner->stream_control_type == RTSP_CONTROL_INDEPENDENT) {		/*re-SETUP failed*/		if (!ch->session_id) {			e = GF_SERVICE_ERROR;			goto err_exit;		}		com->Session = ch->session_id;		return 1;	}	skip_it = 0;	if (!com->Session) {		/*re-SETUP failed*/		if (!strcmp(com->method, GF_RTSP_PLAY) || !strcmp(com->method, GF_RTSP_PAUSE)) {			e = GF_SERVICE_ERROR;			goto err_exit;		}		/*this is a stop, no need for SessionID just skip*/		skip_it = 1;	}	/*check if aggregation discards this command*/	if (skip_it || ( (sess->flags & RTSP_AGG_CONTROL) && (ch->flags & RTP_SKIP_NEXT_COM) )) {		ch->flags &= ~RTP_SKIP_NEXT_COM;		gf_term_on_command(sess->owner->service, &ch_ctrl->com, GF_OK);		free(ch_ctrl);		com->user_data = NULL;		return 0;	}	return 1;err_exit:	gf_rtsp_reset_aggregation(ch->rtsp->session);	ch->status = RTP_Disconnected;	ch->check_rtp_time = 0;	gf_term_on_command(sess->owner->service, &ch_ctrl->com, e);	free(ch_ctrl);	com->user_data = NULL;	return 0;}static void SkipCommandOnSession(RTPStream *ch){	u32 i;	RTPStream *a_ch;	if (!ch || (ch->flags & RTP_SKIP_NEXT_COM) || !(ch->rtsp->flags & RTSP_AGG_CONTROL) ) return;	i=0;	while ((a_ch = (RTPStream *)gf_list_enum(ch->owner->channels, &i))) {		if ((ch == a_ch) || (a_ch->rtsp != ch->rtsp) ) continue;		a_ch->flags |= RTP_SKIP_NEXT_COM;	}}void RP_ProcessUserCommand(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e){	ChannelControl *ch_ctrl;	RTPStream *ch, *agg_ch;	u32 i, count;	GF_RTPInfo *info;	ch_ctrl = (ChannelControl *)com->user_data;	ch = ch_ctrl->ch;	if (!channel_is_valid(sess->owner, ch)) {		free(ch_ctrl);		com->user_data = NULL;		return;	}	assert(ch->channel==ch_ctrl->com.base.on_channel);	/*some consistency checking: on interleaved sessions, some servers do NOT reply to the 	teardown. If our command is STOP just skip the error notif*/	if (e) {		if (!strcmp(com->method, GF_RTSP_TEARDOWN)) {			goto process_reply;		} else {			goto err_exit;		}	}	switch (sess->rtsp_rsp->ResponseCode) {	//handle all 3xx codes  (redirections)	case NC_RTSP_Method_Not_Allowed:		e = GF_NOT_SUPPORTED;		goto err_exit;	case NC_RTSP_OK:		break;	default:		//we should have a basic error code mapping here		e = GF_SERVICE_ERROR;		goto err_exit;	}process_reply:	gf_term_on_command(sess->owner->service, &ch_ctrl->com, GF_OK);	if ( (ch_ctrl->com.command_type==GF_NET_CHAN_PLAY) 		|| (ch_ctrl->com.command_type==GF_NET_CHAN_SET_SPEED)		|| (ch_ctrl->com.command_type==GF_NET_CHAN_RESUME) ) {		//auto-detect any aggregated control if not done yet		if (gf_list_count(sess->rtsp_rsp->RTP_Infos) > 1) {			sess->flags |= RTSP_AGG_CONTROL;		}		//process all RTP infos		count = gf_list_count(sess->rtsp_rsp->RTP_Infos);		for (i=0;i<count; i++) {			info = (GF_RTPInfo*)gf_list_get(sess->rtsp_rsp->RTP_Infos, i);			agg_ch = RP_FindChannel(sess->owner, NULL, 0, info->url, 0);			if (!agg_ch || (agg_ch->rtsp != sess) ) continue;			/*channel is already playing*/			if (agg_ch->status == RTP_Running) {	//			gf_rtp_set_info_rtp(agg_ch->rtp_ch, info->seq, info->rtp_time, info->ssrc);	//			agg_ch->check_rtp_time = 1;				continue;			}						/*if play/seeking we must send update RTP/NPT link*/			if (ch_ctrl->com.command_type != GF_NET_CHAN_RESUME) {				agg_ch->check_rtp_time = 1;			}			/*this is used to discard RTP packets re-sent on resume*/			else {				agg_ch->check_rtp_time = 2;			}			/* reset the buffers */			RP_InitStream(agg_ch, 1);			gf_rtp_set_info_rtp(agg_ch->rtp_ch, info->seq, info->rtp_time, info->ssrc);			agg_ch->status = RTP_Running;			/*skip next play command on this channel if aggregated control*/			if (ch!=agg_ch && (ch->rtsp->flags & RTSP_AGG_CONTROL) ) agg_ch->flags |= RTP_SKIP_NEXT_COM;			if (gf_rtp_is_interleaved(agg_ch->rtp_ch)) {				gf_rtsp_register_interleave(sess->session, 								agg_ch, 								gf_rtp_get_low_interleave_id(agg_ch->rtp_ch), 								gf_rtp_get_hight_interleave_id(agg_ch->rtp_ch));			}		}		/*no rtp info (just in case), no time mapped - set to 0 and specify we're not interactive*/		if (!i) {			ch->current_start = 0.0;			ch->check_rtp_time = 1;			RP_InitStream(ch, 1);			ch->status = RTP_Running;			if (gf_rtp_is_interleaved(ch->rtp_ch)) {				gf_rtsp_register_interleave(sess->session, 								ch, gf_rtp_get_low_interleave_id(ch->rtp_ch), gf_rtp_get_hight_interleave_id(ch->rtp_ch));			}		}		ch->flags &= ~RTP_SKIP_NEXT_COM;	} else if (ch_ctrl->com.command_type == GF_NET_CHAN_PAUSE) {		SkipCommandOnSession(ch);		ch->flags &= ~RTP_SKIP_NEXT_COM;	} else if (ch_ctrl->com.command_type == GF_NET_CHAN_STOP) {		assert(0);	}	free(ch_ctrl);	com->user_data = NULL;	return;err_exit:	ch->status = RTP_Disconnected;	gf_term_on_command(sess->owner->service, &ch_ctrl->com, e);	gf_rtsp_reset_aggregation(ch->rtsp->session);	ch->check_rtp_time = 0;	free(ch_ctrl);	com->user_data = NULL;}static void RP_FlushAndTearDown(RTSPSession *sess){	GF_RTSPCommand *com;	gf_mx_p(sess->owner->mx);	while (gf_list_count(sess->rtsp_commands)) {		com = (GF_RTSPCommand *)gf_list_get(sess->rtsp_commands, 0);		gf_list_rem(sess->rtsp_commands, 0);		gf_rtsp_command_del(com);	}	if (sess->flags & RTSP_WAIT_REPLY) {		GF_Err e;		while (1) {			e = gf_rtsp_get_response(sess->session, sess->rtsp_rsp);			if (e!= GF_IP_NETWORK_EMPTY) break;		}		sess->flags &= ~RTSP_WAIT_REPLY;	}	gf_mx_v(sess->owner->mx);	/*no private stack on teardown - shutdown now*/	com	= gf_rtsp_command_new();	com->method = strdup(GF_RTSP_TEARDOWN);	RP_QueueCommand(sess, NULL, com, 1);}void RP_UserCommand(RTSPSession *sess, RTPStream *ch, GF_NetworkCommand *command){	RTPStream *a_ch;	ChannelControl *ch_ctrl;	u32 i;	GF_RTSPCommand *com;	GF_RTSPRange *range;	assert(ch->rtsp==sess);		/*we may need to re-setup stream/session*/	if ( (command->command_type==GF_NET_CHAN_PLAY) || (command->command_type==GF_NET_CHAN_RESUME) || (command->command_type==GF_NET_CHAN_PAUSE)) {		if (ch->status == RTP_Disconnected) {			if ( (sess->owner->stream_control_type==RTSP_CONTROL_AGGREGATE)				&& (sess->flags & RTSP_AGG_CONTROL)) {				i=0;				while ((a_ch = (RTPStream *)gf_list_enum(sess->owner->channels, &i))) {					if (a_ch->rtsp != sess) continue;					if (a_ch->status == RTP_Disconnected) 						RP_Setup(a_ch);				}			} else {				RP_Setup(ch);			}		}	}		com	= gf_rtsp_command_new();	range = NULL;	if ( (command->command_type==GF_NET_CHAN_PLAY) || (command->command_type==GF_NET_CHAN_RESUME) ) {		range = gf_rtsp_range_new();		range->start = ch->range_start;		range->end = ch->range_end;				com->method = strdup(GF_RTSP_PLAY);				/*specify pause range on resume - this is not mandatory but most servers need it*/		if (command->command_type==GF_NET_CHAN_RESUME) {			range->start = ch->current_start;			ch->stat_start_time -= ch->stat_stop_time;			ch->stat_start_time += gf_sys_clock();			ch->stat_stop_time = 0;		} else {			range->start = ch->range_start;			if (command->play.start_range>=0) range->start += command->play.start_range;			range->end = ch->range_start;			if (command->play.end_range >=0) {				range->end += command->play.end_range;				if (range->end > ch->range_end) range->end = ch->range_end;			}			ch->stat_start_time = gf_sys_clock();			ch->stat_stop_time = 0;		}		/*if aggregated the command is sent once, so store info at session level*/		if (ch->flags & RTP_SKIP_NEXT_COM) {			ch->current_start = ch->rtsp->last_range;		} else {			ch->rtsp->last_range = range->start;			ch->current_start = range->start;		}		/*some RTSP servers don't accept Range=npt:0.0- (for ex, broadcast only...), so skip it if:		- a range was given in initial describe		- the command is not a RESUME		*/		if (!(ch->flags & RTP_HAS_RANGE) && (command->command_type != GF_NET_CHAN_RESUME) ) {			gf_rtsp_range_del(range);			com->Range = NULL;		} else {			com->Range = range;		}		if (!(sess->flags & RTSP_AGG_CONTROL) && strlen(ch->control)) com->ControlString = strdup(ch->control);		if (RP_SessionActive(ch)) {			if (!com->ControlString && ch->control) com->ControlString = strdup(ch->control);		} else {			if ((sess->owner->stream_control_type!=RTSP_CONTROL_INDEPENDENT) && com->ControlString) {				free(com->ControlString);				com->ControlString=NULL;			}		}	} else if (command->command_type==GF_NET_CHAN_PAUSE) {		range = gf_rtsp_range_new();		range->start = ch->range_start;		range->end = ch->range_end;		com->method = strdup(GF_RTSP_PAUSE);		/*update current time*/		ch->current_start += gf_rtp_get_current_time(ch->rtp_ch);		range->start = ch->current_start;		range->end = -1.0;		com->Range = range;		ch->stat_stop_time = gf_sys_clock();	}	//nb: we could actually send a PAUSE in order to keep the session alive	//but let's be nice to the server	else if (command->command_type==GF_NET_CHAN_STOP) {		ch->current_start = 0;		ch->stat_stop_time = gf_sys_clock();		RP_StopChannel(ch);		if (com) gf_rtsp_command_del(com);		/*use stream-control*/		switch (ch->owner->stream_control_type) {		case RTSP_CONTROL_AGGREGATE:			/*last stream running*/			//if (!RP_SessionActive(ch)) RP_FlushAndTearDown(sess);			break;		/*FIXME - according to trhe current draft, the stream's session must be paused before ...*/		case RTSP_CONTROL_RTSP_V2:		case RTSP_CONTROL_INDEPENDENT:		default:			RP_Teardown(sess, ch);			break;		}		return;	} else {		gf_term_on_command(sess->owner->service, command, GF_NOT_SUPPORTED);		gf_rtsp_command_del(com);		return;	}	ch_ctrl = (ChannelControl *)malloc(sizeof(ChannelControl));	ch_ctrl->ch = ch;	memcpy(&ch_ctrl->com, command, sizeof(GF_NetworkCommand));	com->user_data = ch_ctrl;	RP_QueueCommand(sess, ch, com, 1);	return;}/* 						session/channel teardown functions																*/void RP_ProcessTeardown(RTSPSession *sess, GF_RTSPCommand *com, GF_Err e){	RTPStream *ch = (RTPStream *)com->user_data;	if (ch) {		if (ch->session_id) free(ch->session_id);		ch->session_id = NULL;	} else {		if (sess->session_id) free(sess->session_id);		sess->session_id = NULL;	}}void RP_Teardown(RTSPSession *sess, RTPStream *ch){	GF_RTSPCommand *com;	switch (sess->owner->stream_control_type) {	case RTSP_CONTROL_AGGREGATE:		/*we need a session id*/		if (!sess->session_id) return;		/*ignore teardown on channels*/		if ((sess->flags & RTSP_AGG_CONTROL) && ch) return;		break;	case RTSP_CONTROL_RTSP_V2:		/*we need a session id*/		if (!sess->session_id) return;		/*do not ignore teardown on channels*/		break;	case RTSP_CONTROL_INDEPENDENT:		/*todo*/		break;	}	com = gf_rtsp_command_new();	com->method = strdup(GF_RTSP_TEARDOWN);	if (ch && ch->control && (sess->owner->stream_control_type == RTSP_CONTROL_RTSP_V2)) {		com->ControlString = strdup(ch->control);		com->user_data = ch;	}	RP_QueueCommand(sess, ch, com, 1);}

⌨️ 快捷键说明

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