Beispiel #1
0
/*filter setup if no session (rtp only)*/
M4Err RP_SetupChannel(RTPStream *ch, ChannelDescribe *ch_desc)
{
	M4Err resp;

	/*assign ES_ID of the channel*/
	if (ch_desc && !ch->ES_ID && ch_desc->ES_ID) ch->ES_ID = ch_desc->ES_ID;

	ch->status = RTP_Setup;

	/*assign channel handle if not done*/
	if (ch_desc && ch->channel) {
		assert(ch->channel == ch_desc->channel);
	} else if (!ch->channel) {
		assert(ch_desc);
		assert(ch_desc->channel);
		ch->channel = ch_desc->channel;
	}

	/*no session , setup for pure rtp*/
	if (!ch->rtsp) {
		ch->connected = 1;
		/*init rtp*/
		resp = RP_InitStream(ch, 0),
		/*send confirmation to user*/
		RP_ConfirmChannelConnect(ch, resp);
	} else {
		RP_Setup(ch);
	}
	return M4OK;
}
Beispiel #2
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;
}
Beispiel #3
0
void RP_ProcessSetup(RTPSession *sess, RTSPCommand *com, M4Err e)
{
	RTPStream *ch;
	u32 i;
	RTSPTransport *trans;
	
	
	ch = com->user_data;
	if (e) goto exit;

	switch (sess->rtsp_rsp->ResponseCode) {
	case NC_RTSP_OK:
		break;
	case NC_RTSP_Not_Found:
		e = M4ChannelNotFound;
		goto exit;
	default:
		e = M4ServiceError;
		goto exit;
	}
	e = M4ServiceError;
	if (!ch) goto exit;

	/*transport setup: break at the first correct transport */
	for (i=0; i<ChainGetCount(sess->rtsp_rsp->Transports); i++) {
		trans = ChainGetEntry(sess->rtsp_rsp->Transports, 0);
		e = RTP_SetupTransport(ch->rtp_ch, trans, RTSP_GetServerName(sess->session));
		if (!e) break;
	}
	if (e) goto exit;

	e = RP_InitStream(ch, 0);
	if (e) goto exit;
	ch->status = RTP_Connected;

	//in case this is TCP channel, setup callbacks
	ch->is_interleaved = RTP_IsInterleaved(ch->rtp_ch);
	if (ch->is_interleaved) {
		RTSP_SetCallbackOnInterleaving(sess->session, RP_DataOnTCP);
	}

exit:
	/*confirm only on first connect, otherwise this is a re-SETUP of the rtsp session, not the channel*/
	if (! ch->connected) {
		ch->connected = 1;
		RP_ConfirmChannelConnect(ch, e);
	}
	com->user_data = NULL;
}
Beispiel #4
0
static GF_Err RP_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
{
	u32 ESID;
	RTPStream *ch;
	RTSPSession *sess;
	char *es_url;
	RTPClient *priv = (RTPClient *)plug->priv;
	if (upstream) return GF_NOT_SUPPORTED;


	GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] Connecting channel @%08x - %s\n", channel, url));

	ch = RP_FindChannel(priv, channel, 0, (char *) url, 0);
	if (ch && (ch->status != RTP_Disconnected) ) return GF_SERVICE_ERROR;

	es_url = NULL;
	sess = NULL;
	if (strstr(url, "ES_ID=")) {
		sscanf(url, "ES_ID=%ud", &ESID);
		/*first case: simple URL (same namespace)*/
		ch = RP_FindChannel(priv, NULL, ESID, NULL, 0);
		/*this should not happen, the sdp must describe all streams in the service*/
		if (!ch) return GF_STREAM_NOT_FOUND;

		/*assign app channel*/
		ch->channel = channel;
		sess = ch->rtsp;
	}
	/*rtsp url - create a session if needed*/
	else if (!strnicmp(url, "rtsp://", 7) || !strnicmp(url, "rtspu://", 8)) {
		sess = RP_CheckSession(priv, (char *) url);
		if (!sess) sess = RP_NewSession(priv, (char *) url);
		es_url = (char *) url;
	}
	/*data: url*/
	else if (strstr(url, "data:application/mpeg4-od-au;base64")
		|| strstr(url, "data:application/mpeg4-bifs-au;base64")
		|| strstr(url, "data:application/mpeg4-es-au;base64")
		) {

		GF_SAFEALLOC(ch, RTPStream);
		ch->control = gf_strdup(url);
		ch->owner = priv;
		ch->channel = channel;
		ch->status = RTP_Connected;
		/*register*/
		gf_list_add(priv->channels, ch);
		RP_ConfirmChannelConnect(ch, GF_OK);

		return GF_OK;
	}
	/*session migration resume - don't send data to the server*/
	if (ch->status==RTP_SessionResume) {
		ch->flags |= RTP_CONNECTED;
		RP_InitStream(ch, 0);
		RP_ConfirmChannelConnect(ch, GF_OK);
		return GF_OK;
	}
	/*send a DESCRIBE (not a setup) on the channel. If the channel is already created then the
	describe is skipped and a SETUP is sent directly, otherwise the channel is first described then setup*/
	if (sess) RP_Describe(sess, es_url, channel);
	/*otherwise confirm channel connection*/
	else RP_ConfirmChannelConnect(ch, GF_OK);

	return GF_OK;
}