Exemple #1
0
/*process describe reply*/
void RP_ProcessDescribe(RTPSession *sess, RTSPCommand *com, M4Err e)
{
	RTPStream *ch;
	ChannelDescribe *ch_desc;

	ch = NULL;
	ch_desc = com->user_data;
	if (e) goto exit;

	switch (sess->rtsp_rsp->ResponseCode) {
	//TODO handle all 3xx codes  (redirections)
	case NC_RTSP_Multiple_Choice:
		e = ch_desc ? M4ChannelNotFound : M4URLNotFound;
		goto exit;
	case NC_RTSP_Not_Found:
		e = M4URLNotFound;
		goto exit;
	case NC_RTSP_OK:
		break;
	default:
		//we should have a basic error code mapping here
		e = M4ServiceError;
		goto exit;
	}

	ch = NULL;
	if (ch_desc) {
		ch = RP_FindChannel(sess->owner, ch_desc->channel, ch_desc->ES_ID, ch_desc->esd_url, 0);
	} else {
		NM_OnMessage(sess->owner->service, M4OK, "Connected");
	}

	/*error on loading SDP is done internally*/
	RP_LoadSDP(sess->owner, sess->rtsp_rsp->body, sess->rtsp_rsp->Content_Length, ch);

	if (!ch_desc) goto exit;
	if (!ch) {
		e = M4ChannelNotFound;
		goto exit;
	}
	e = RP_SetupChannel(ch, ch_desc);

exit:
	if (e) {
		if (!ch_desc) {
			NM_OnConnect(sess->owner->service, NULL, e);
		} else if (ch) {
			RP_ConfirmChannelConnect(ch, e);
		} else {
			NM_OnConnect(sess->owner->service, ch_desc->channel, e);
		}
	}
	if (ch_desc) free(ch_desc);
	com->user_data = NULL;
}
Exemple #2
0
/*send describe*/
void RP_Describe(RTPSession *sess, char *esd_url, LPNETCHANNEL channel)
{
	RTPStream *ch;
	ChannelDescribe *ch_desc;
	RTSPCommand *com;

	/*locate the channel by URL - if we have one, this means the channel is already described
	this happens when 2 ESD with URL use the same RTSP service - skip describe and send setup*/
	if (esd_url || channel) {
		ch = RP_FindChannel(sess->owner, channel, 0, esd_url, 0);
		if (ch) {
			if (!ch->channel) ch->channel = channel;
			ch_desc = malloc(sizeof(ChannelDescribe));
			ch_desc->esd_url = esd_url ? strdup(esd_url) : NULL;
			ch_desc->channel = channel;
			RP_SetupChannel(ch, ch_desc);
			
			if (esd_url) free(ch_desc->esd_url);
			free(ch_desc);
			return;
		}
		/*channel not found, send describe on service*/
	}

	/*send describe*/
	com = RTSP_NewCommand();
	com->method = strdup(RTSP_DESCRIBE);

	if (channel || esd_url) {
		com->Accept = strdup("application/sdp");
		com->ControlString = esd_url ? strdup(esd_url) : NULL;

		ch_desc = malloc(sizeof(ChannelDescribe));
		ch_desc->esd_url = esd_url ? strdup(esd_url) : NULL;
		ch_desc->channel = channel;
		
		com->user_data = ch_desc;
	} else {
		//always accept both SDP and IOD
		com->Accept = strdup("application/sdp, application/mpeg4-iod");
//		com->Accept = strdup("application/sdp");
	}
	com->Bandwidth = sess->owner->bandwidth;

	MX_P(sess->owner->mx);
	ChainAddEntry(sess->rtsp_commands, com);
	MX_V(sess->owner->mx);
}
Exemple #3
0
/*filter describe commands in case of ESD URLs*/
Bool RP_PreprocessDescribe(RTPSession *sess, RTSPCommand *com)
{
	RTPStream *ch;
	ChannelDescribe *ch_desc;
	/*not a channel describe*/
	if (!com->user_data) {
		NM_OnMessage(sess->owner->service, M4OK, "Connecting...");
		return 1;
	}

	ch_desc = (ChannelDescribe *)com->user_data;
	ch = RP_FindChannel(sess->owner, NULL, ch_desc->ES_ID, ch_desc->esd_url, 0);
	if (!ch) return 1;

	/*channel has been described already, skip describe and send setup directly*/
	RP_SetupChannel(ch, ch_desc);
	
	if (ch_desc->esd_url) free(ch_desc->esd_url);
	free(ch_desc);
	return 0;
}
Exemple #4
0
void RP_LoadSDP(RTPClient *rtp, char *sdp_text, u32 sdp_len, RTPStream *stream)
{
	GF_Err e;
	u32 i;
	GF_SDPInfo *sdp;
	Bool is_isma_1, has_iod;
	char *iod_str;
	GF_X_Attribute *att;

	is_isma_1 = 0;
	iod_str = NULL;
	sdp = gf_sdp_info_new();
	e = gf_sdp_info_parse(sdp, sdp_text, sdp_len);

	if (e == GF_OK) e = RP_SetupSDP(rtp, sdp, stream);

	/*root SDP, attach service*/
	if (! stream) {
		/*look for IOD*/
		if (e==GF_OK) {
			i=0;
			while ((att = (GF_X_Attribute*)gf_list_enum(sdp->Attributes, &i))) {
				if (!iod_str && !strcmp(att->Name, "mpeg4-iod") ) iod_str = att->Value;
				if (!is_isma_1 && !strcmp(att->Name, "isma-compliance") ) {
					if (!stricmp(att->Value, "1,1.0,1")) is_isma_1 = 1;
				}
			}

			/*force iod reconstruction with ISMA to use proper clock dependencies*/
			if (is_isma_1) iod_str = NULL;

			/*some folks have weird notions of MPEG-4 systems, they use hardcoded IOD
			with AAC ESD even when streaming AMR...*/
			if (iod_str) {
				RTPStream *ch;
				i=0;
				while ((ch = (RTPStream *)gf_list_enum(rtp->channels, &i))) {
					if ((ch->depacketizer->payt==GF_RTP_PAYT_AMR) || (ch->depacketizer->payt==GF_RTP_PAYT_AMR_WB) ) {
						iod_str = NULL;
						break;
					}
				}
			}
			if (!iod_str) {
				RTPStream *ch;
				Bool needs_iod = 0;
				i=0;
				while ((ch = (RTPStream *)gf_list_enum(rtp->channels, &i))) {
					if ((ch->depacketizer->payt==GF_RTP_PAYT_MPEG4) && (ch->depacketizer->sl_map.StreamType==GF_STREAM_SCENE)
//						|| ((ch->depacketizer->payt==GF_RTP_PAYT_3GPP_DIMS) && (ch->depacketizer->sl_map.StreamType==GF_STREAM_SCENE))
						) {
						needs_iod = 1;
						break;
					}
				}
				if (needs_iod) {
					rtp->session_desc = (GF_Descriptor *)RP_GetChannelOD(ch, 0);
				}
			}

			if (iod_str) e = RP_SDPLoadIOD(rtp, iod_str);
		}
		/*attach service*/
		has_iod = rtp->session_desc ? 1 : 0;
		gf_term_on_connect(rtp->service, NULL, e);
		if (!e && !has_iod && !rtp->media_type) RP_SetupObjects(rtp);
		rtp->media_type = 0;
	}
	/*channel SDP */
	else {
		if (e) {
			gf_term_on_connect(rtp->service, stream->channel, e);
			stream->status = RTP_Unavailable;
		} else {
			/*connect*/
			RP_SetupChannel(stream, NULL);
		}
	}
	/*store SDP for later session migration*/
	if (sdp) {
		char *buf=NULL;
		gf_sdp_info_write(sdp, &buf);
		if (buf) {
			rtp->session_state_data = gf_malloc(sizeof(char) * (strlen("data:application/sdp,") + strlen(buf) + 1) );
			strcpy(rtp->session_state_data, "data:application/sdp,");
			strcat(rtp->session_state_data, buf);
			gf_free(buf);
		}
		gf_sdp_info_del(sdp);
	}
}