/*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; }
/*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; }
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; }
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; }