コード例 #1
0
ファイル: rtsp_command.c プロジェクト: Keemotion/GPAC4iOS
void gf_rtsp_set_command_value(GF_RTSPCommand *com, char *Header, char *Value)
{
	char LineBuffer[400];
	s32 LinePos;
	GF_RTSPTransport *trans;
	GF_X_Attribute *x_Att;

	if (!stricmp(Header, "Accept")) com->Accept = gf_strdup(Value);
	else if (!stricmp(Header, "Accept-Encoding")) com->Accept_Encoding = gf_strdup(Value);
	else if (!stricmp(Header, "Accept-Language")) com->Accept_Language = gf_strdup(Value);
	else if (!stricmp(Header, "Authorization")) com->Authorization = gf_strdup(Value);
	else if (!stricmp(Header, "Bandwidth")) sscanf(Value, "%u", &com->Bandwidth);
	else if (!stricmp(Header, "Blocksize")) sscanf(Value, "%u", &com->Blocksize);
	else if (!stricmp(Header, "Cache-Control")) com->Cache_Control = gf_strdup(Value);
	else if (!stricmp(Header, "Conference")) com->Conference = gf_strdup(Value);
	else if (!stricmp(Header, "Connection")) com->Connection = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Length")) sscanf(Value, "%u", &com->Content_Length);
	else if (!stricmp(Header, "CSeq")) sscanf(Value, "%u", &com->CSeq);
	else if (!stricmp(Header, "From")) com->From = gf_strdup(Value);
	else if (!stricmp(Header, "Proxy_Authorization")) com->Proxy_Authorization = gf_strdup(Value);
	else if (!stricmp(Header, "Proxy_Require")) com->Proxy_Require = gf_strdup(Value);
	else if (!stricmp(Header, "Range")) com->Range = gf_rtsp_range_parse(Value);
	else if (!stricmp(Header, "Referer")) com->Referer = gf_strdup(Value);
	else if (!stricmp(Header, "Scale")) sscanf(Value, "%lf", &com->Scale);
	else if (!stricmp(Header, "Session")) com->Session = gf_strdup(Value);
	else if (!stricmp(Header, "Speed")) sscanf(Value, "%lf", &com->Speed);
	else if (!stricmp(Header, "User_Agent")) com->User_Agent = gf_strdup(Value);
	//Transports
	else if (!stricmp(Header, "Transport")) {
		LinePos = 0;
		while (1) {
			LinePos = gf_token_get(Value, LinePos, "\r\n", LineBuffer, 400);
			if (LinePos <= 0) return;
			trans = gf_rtsp_transport_parse(Value);
			if (trans) gf_list_add(com->Transports, trans);
		}
	}
	//eXtensions attributes
	else if (!strnicmp(Header, "x-", 2)) {
		x_Att = (GF_X_Attribute*)gf_malloc(sizeof(GF_X_Attribute));
		x_Att->Name = gf_strdup(Header+2);
		x_Att->Value = NULL;
		if (Value && strlen(Value)) x_Att->Value = gf_strdup(Value);
		gf_list_add(com->Xtensions, x_Att);
	}
	//the rest is ignored
}
コード例 #2
0
ファイル: rtsp_response.c プロジェクト: ARSekkat/gpac
void gf_rtsp_set_response_value(GF_RTSPResponse *rsp, char *Header, char *Value)
{
	char LineBuffer[400], buf[1000], param_name[100], param_val[1000];
	s32 LinePos, Pos, nPos, s_val;
	GF_RTPInfo *info;
	GF_RTSPTransport *trans;
	GF_X_Attribute *x_Att;

	if (!stricmp(Header, "Accept")) rsp->Accept = gf_strdup(Value);
	else if (!stricmp(Header, "Accept-Encoding")) rsp->Accept_Encoding = gf_strdup(Value);
	else if (!stricmp(Header, "Accept-Language")) rsp->Accept_Language = gf_strdup(Value);
	else if (!stricmp(Header, "Allow")) rsp->Allow = gf_strdup(Value);
	else if (!stricmp(Header, "Authorization")) rsp->Authorization = gf_strdup(Value);
	else if (!stricmp(Header, "Bandwidth")) sscanf(Value, "%u", &rsp->Bandwidth);
	else if (!stricmp(Header, "Blocksize")) sscanf(Value, "%u", &rsp->Blocksize);
	else if (!stricmp(Header, "Cache-Control")) rsp->Cache_Control = gf_strdup(Value);
	else if (!stricmp(Header, "com.ses.streamID")) sscanf(Value, "%u", &rsp->StreamID);
	else if (!stricmp(Header, "Conference")) rsp->Conference = gf_strdup(Value);
	else if (!stricmp(Header, "Connection")) rsp->Connection = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Base")) rsp->Content_Base = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Encoding")) rsp->Content_Encoding = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Length")) sscanf(Value, "%u", &rsp->Content_Length);
	else if (!stricmp(Header, "Content-Language")) rsp->Content_Language = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Location")) rsp->Content_Location = gf_strdup(Value);
	else if (!stricmp(Header, "Content-Type")) rsp->Content_Type = gf_strdup(Value);
	else if (!stricmp(Header, "CSeq")) sscanf(Value, "%u", &rsp->CSeq);
	else if (!stricmp(Header, "Date")) rsp->Date = gf_strdup(Value);
	else if (!stricmp(Header, "Expires")) rsp->Expires = gf_strdup(Value);
	else if (!stricmp(Header, "From")) rsp->From = gf_strdup(Value);
	else if (!stricmp(Header, "Host")) rsp->Host = gf_strdup(Value);
	else if (!stricmp(Header, "If-Match")) rsp->If_Match = gf_strdup(Value);
	else if (!stricmp(Header, "If-Modified-Since")) rsp->If_Modified_Since = gf_strdup(Value);
	else if (!stricmp(Header, "Last-Modified")) rsp->Last_Modified = gf_strdup(Value);
	else if (!stricmp(Header, "Location")) rsp->Location = gf_strdup(Value);
	else if (!stricmp(Header, "Proxy-Authenticate")) rsp->Proxy_Authenticate = gf_strdup(Value);
	else if (!stricmp(Header, "Proxy-Require")) rsp->Proxy_Require = gf_strdup(Value);
	else if (!stricmp(Header, "Public")) rsp->Public = gf_strdup(Value);
	else if (!stricmp(Header, "Referer")) rsp->Referer = gf_strdup(Value);
	else if (!stricmp(Header, "Require")) rsp->Require = gf_strdup(Value);
	else if (!stricmp(Header, "Retry-After")) rsp->Retry_After = gf_strdup(Value);
	else if (!stricmp(Header, "Scale")) sscanf(Value, "%lf", &rsp->Scale);
	else if (!stricmp(Header, "Server")) rsp->Server = gf_strdup(Value);
	else if (!stricmp(Header, "Speed")) sscanf(Value, "%lf", &rsp->Speed);
	else if (!stricmp(Header, "Timestamp")) rsp->Timestamp = gf_strdup(Value);
	else if (!stricmp(Header, "Unsupported")) rsp->Unsupported = gf_strdup(Value);
	else if (!stricmp(Header, "User-Agent")) rsp->User_Agent = gf_strdup(Value);
	else if (!stricmp(Header, "Vary")) rsp->Vary = gf_strdup(Value);
	else if (!stricmp(Header, "Via")) rsp->Vary = gf_strdup(Value);
	else if (!stricmp(Header, "WWW_Authenticate")) rsp->Vary = gf_strdup(Value);
	else if (!stricmp(Header, "Transport")) {
		LinePos = 0;
		while (1) {
			LinePos = gf_token_get(Value, LinePos, "\r\n", LineBuffer, 400);
			if (LinePos <= 0) return;
			trans = gf_rtsp_transport_parse(Value);
			if (trans) gf_list_add(rsp->Transports, trans);
		}
	}
	//Session
	else if (!stricmp(Header, "Session")) {
		LinePos = gf_token_get(Value, 0, ";\r\n", LineBuffer, 400);
		rsp->Session = gf_strdup(LineBuffer);
		//get timeout if any
		if (Value[LinePos] == ';') {
			LinePos += 1;
			/*LinePos = */gf_token_get(Value, LinePos, ";\r\n", LineBuffer, 400);
			rsp->SessionTimeOut = 60; //default
			sscanf(LineBuffer, "timeout=%u", &rsp->SessionTimeOut);
		}
	}

	//Range
	else if (!stricmp(Header, "Range")) rsp->Range = gf_rtsp_range_parse(Value);
	//RTP-Info
	else if (!stricmp(Header, "RTP-Info")) {
		LinePos = 0;
		while (1) {
			LinePos = gf_token_get(Value, LinePos, ",\r\n", LineBuffer, 400);
			if (LinePos <= 0) return;

			GF_SAFEALLOC(info, GF_RTPInfo);
			if (!info) return;

			Pos = 0;
			while (1) {
				Pos = gf_token_get(LineBuffer, Pos, " ;", buf, 1000);
				if (Pos <= 0) break;
				if (strstr(buf, "=")) {
					nPos = gf_token_get(buf, 0, "=", param_name, 100);
					nPos += 1;
					/*nPos = */gf_token_get(buf, nPos, "", param_val, 1000);
				} else {
					strcpy(param_name, buf);
				}
				if (!stricmp(param_name, "url")) info->url = gf_strdup(param_val);
				else if (!stricmp(param_name, "seq")) sscanf(param_val, "%u", &info->seq);
				else if (!stricmp(param_name, "rtptime")) {
					sscanf(param_val, "%i", &s_val);
					info->rtp_time = (s_val>0) ? s_val : 0;
				}
				else if (!stricmp(param_name, "ssrc")) {
					sscanf(param_val, "%i", &s_val);
					info->ssrc = (s_val>0) ? s_val : 0;
				}
			}
			gf_list_add(rsp->RTP_Infos, info);
		}
	}
	//check for extended attributes
	else if (!strnicmp(Header, "x-", 2)) {
		x_Att = (GF_X_Attribute*)gf_malloc(sizeof(GF_X_Attribute));
		x_Att->Name = gf_strdup(Header+2);
		x_Att->Value = NULL;
		if (Value && strlen(Value)) x_Att->Value = gf_strdup(Value);
		gf_list_add(rsp->Xtensions, x_Att);
	}
	//unknown field - skip it
}
コード例 #3
0
ファイル: sdp_load.c プロジェクト: erelh/gpac
GF_Err RP_SetupSDP(RTPClient *rtp, GF_SDPInfo *sdp, RTPStream *stream)
{
	GF_Err e;
	GF_SDPMedia *media;
	Double Start, End;
	u32 i;
	char *sess_ctrl, *session_id, *url;
	GF_X_Attribute *att;
	GF_RTSPRange *range;
	RTPStream *ch;
	RTSPSession *migrate_sess = NULL;

	Start = 0.0;
	End = -1.0;

	sess_ctrl = NULL;
	range = NULL;
	session_id = url = NULL;

	i=0;
	while ((att = (GF_X_Attribute*)gf_list_enum(sdp->Attributes, &i))) {
		//session-level control string. Keep it in the current session if any
		if (!strcmp(att->Name, "control") && att->Value) sess_ctrl = att->Value;
		//NPT range only for now
		else if (!strcmp(att->Name, "range") && !range) range = gf_rtsp_range_parse(att->Value);
		/*session migration*/
		else if (!strcmp(att->Name, "x-session-name")) url = att->Value;
		else if (!strcmp(att->Name, "x-session-id")) session_id = att->Value;
		/*we have the H264-SVC streams*/
		else if (!strcmp(att->Name, "group") && !strncmp(att->Value, "DDP", 3)) rtp->is_svc = 1;
	}
	if (range) {
		Start = range->start;
		End = range->end;
		gf_rtsp_range_del(range);
	}

	if (url) {
		migrate_sess = RP_NewSession(rtp, url);
		if (migrate_sess && session_id) {
			migrate_sess->session_id = gf_strdup(session_id);
		}
		sess_ctrl = url;
	}

	//setup all streams
	i=0;
	while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) {
		ch = RP_NewStream(rtp, media, sdp, stream);
		//do not generate error if the channel is not created, just assume
		//1 - this is not an MPEG-4 configured channel -> not needed
		//2 - this is a 2nd describe and the channel was already created
		if (!ch) continue;

		e = RP_AddStream(rtp, ch, sess_ctrl);
		if (e) {
			RP_DeleteStream(ch);
			return e;
		}

		if (!(ch->flags & RTP_HAS_RANGE)) {
			ch->range_start = Start;
			ch->range_end = End;
			if (End > 0) ch->flags |= RTP_HAS_RANGE;
		}

		/*force interleaving whenever needed*/
		if (ch->rtsp) {
			switch (ch->depacketizer->sl_map.StreamType) {
			case GF_STREAM_VISUAL:
			case GF_STREAM_AUDIO:
				if ((rtp->transport_mode==1) && ! (ch->rtsp->flags & RTSP_FORCE_INTER) ) {
					gf_rtsp_set_buffer_size(ch->rtsp->session, RTSP_TCP_BUFFER_SIZE);
					ch->rtsp->flags |= RTSP_FORCE_INTER;
				}
				break;
			default:
				if (rtp->transport_mode && ! (ch->rtsp->flags & RTSP_FORCE_INTER) ) {
					gf_rtsp_set_buffer_size(ch->rtsp->session, RTSP_TCP_BUFFER_SIZE);
					ch->rtsp->flags |= RTSP_FORCE_INTER;
				}
				break;
			}
		}

	}
	return GF_OK;
}
コード例 #4
0
ファイル: rtp_stream.c プロジェクト: OpenHEVC/gpac
RTPStream *RP_NewStream(RTPClient *rtp, GF_SDPMedia *media, GF_SDPInfo *sdp, RTPStream *input_stream)
{
	GF_RTSPRange *range;
	RTPStream *tmp;
	GF_RTPMap *map;
	u32 i, ESID, ODID, ssrc, rtp_seq, rtp_time;
	Bool force_bcast = 0;
	Double Start, End;
	Float CurrentTime;
	u16 rvc_predef = 0;
	char *rvc_config_att = NULL;
	u32 s_port_first, s_port_last;
	GF_X_Attribute *att;
	Bool is_migration = 0;
	char *ctrl;
	GF_SDPConnection *conn;
	GF_RTSPTransport trans;
	u32 mid, prev_stream, base_stream;

	//extract all relevant info from the GF_SDPMedia
	Start = 0.0;
	End = -1.0;
	CurrentTime = 0.0f;
	ODID = 0;
	ESID = 0;
	ctrl = NULL;
	range = NULL;
	s_port_first = s_port_last = 0;
	ssrc = rtp_seq = rtp_time = 0;
	mid = prev_stream = base_stream = 0;
	i=0;
	while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) {
		if (!stricmp(att->Name, "control")) ctrl = att->Value;
		else if (!stricmp(att->Name, "gpac-broadcast")) force_bcast = 1;
		else if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ESID = atoi(att->Value);
		else if (!stricmp(att->Name, "mpeg4-odid") && att->Value) ODID = atoi(att->Value);
		else if (!stricmp(att->Name, "range") && !range) range = gf_rtsp_range_parse(att->Value);
		else if (!stricmp(att->Name, "x-stream-state") ) {
			sscanf(att->Value, "server-port=%u-%u;ssrc=%X;npt=%g;seq=%u;rtptime=%u",
			       &s_port_first, &s_port_last, &ssrc, &CurrentTime, &rtp_seq, &rtp_time);
			is_migration = 1;
		}
		else if (!stricmp(att->Name, "x-server-port") ) {
			sscanf(att->Value, "%u-%u", &s_port_first, &s_port_last);
		} else if (!stricmp(att->Name, "rvc-config-predef")) {
			rvc_predef = atoi(att->Value);
		} else if (!stricmp(att->Name, "rvc-config")) {
			rvc_config_att = att->Value;
		} else if (!stricmp(att->Name, "mid")) {
			sscanf(att->Value, "L%d", &mid);
		} else if (!stricmp(att->Name, "depend")) {
			char buf[3000];
			memset(buf, 0, 3000);
			sscanf(att->Value, "%*d lay L%d %*s %s", &base_stream, buf);
			if (!strlen(buf))
				sscanf(att->Value, "%*d lay %s", buf);
			sscanf(buf, "L%d", &prev_stream);
		}
	}

	if (range) {
		Start = range->start;
		End = range->end;
		gf_rtsp_range_del(range);
	}

	/*check connection*/
	conn = sdp->c_connection;
	if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL;

	if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0);
	if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL;

	if (!conn) {
		/*RTSP RFC recommends an empty "c= " line but some server don't send it. Use session info (o=)*/
		if (!sdp->o_net_type || !sdp->o_add_type || strcmp(sdp->o_net_type, "IN")) return NULL;
		if (strcmp(sdp->o_add_type, "IP4") && strcmp(sdp->o_add_type, "IP6")) return NULL;
	} else {
		if (strcmp(conn->net_type, "IN")) return NULL;
		if (strcmp(conn->add_type, "IP4") && strcmp(conn->add_type, "IP6")) return NULL;
	}
	/*do we support transport*/
	if (strcmp(media->Profile, "RTP/AVP") && strcmp(media->Profile, "RTP/AVP/TCP")
	        && strcmp(media->Profile, "RTP/SAVP") && strcmp(media->Profile, "RTP/SAVP/TCP")
	   ) return NULL;

	/*check RTP map. For now we only support 1 RTPMap*/
	if (media->fmt_list || (gf_list_count(media->RTPMaps) > 1)) return NULL;

	/*check payload type*/
	map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0);

	/*this is an ESD-URL setup, we likely have namespace conflicts so overwrite given ES_ID
	by the app one (client side), but keep control (server side) if provided*/
	if (input_stream) {
		ESID = input_stream->ES_ID;
		if (!ctrl) ctrl = input_stream->control;
		tmp = input_stream;
	} else {
		tmp = RP_FindChannel(rtp, NULL, ESID, NULL, 0);
		if (tmp) return NULL;

		GF_SAFEALLOC(tmp, RTPStream);
		tmp->owner = rtp;
	}

	/*create an RTP channel*/
	tmp->rtp_ch = gf_rtp_new();
	if (ctrl) tmp->control = gf_strdup(ctrl);
	tmp->ES_ID = ESID;
	tmp->OD_ID = ODID;
	tmp->mid = mid;
	tmp->prev_stream = prev_stream;
	tmp->base_stream = base_stream;

	memset(&trans, 0, sizeof(GF_RTSPTransport));
	trans.Profile = media->Profile;
	trans.source = conn ? conn->host : sdp->o_address;
	trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? 0 : 1;
	if (!trans.IsUnicast) {
		trans.port_first = media->PortNumber;
		trans.port_last = media->PortNumber + 1;
		trans.TTL = conn ? conn->TTL : 0;
	} else {
		trans.client_port_first = media->PortNumber;
		trans.client_port_last = media->PortNumber + 1;
		trans.port_first = s_port_first ? s_port_first : trans.client_port_first;
		trans.port_last = s_port_last ? s_port_last : trans.client_port_last;
	}

	if (gf_rtp_setup_transport(tmp->rtp_ch, &trans, NULL) != GF_OK) {
		RP_DeleteStream(tmp);
		return NULL;
	}
	/*setup depacketizer*/
	tmp->depacketizer = gf_rtp_depacketizer_new(media, rtp_sl_packet_cbk, tmp);
	if (!tmp->depacketizer) {
		RP_DeleteStream(tmp);
		return NULL;
	}
	/*setup channel*/
	gf_rtp_setup_payload(tmp->rtp_ch, map);

//	tmp->status = NM_Disconnected;

	ctrl = (char *) gf_modules_get_option((GF_BaseInterface *) gf_term_get_service_interface(rtp->service), "Streaming", "DisableRTCP");
	if (!ctrl || stricmp(ctrl, "yes")) tmp->flags |= RTP_ENABLE_RTCP;

	/*setup NAT keep-alive*/
	ctrl = (char *) gf_modules_get_option((GF_BaseInterface *) gf_term_get_service_interface(rtp->service), "Streaming", "NATKeepAlive");
	if (ctrl) gf_rtp_enable_nat_keepalive(tmp->rtp_ch, atoi(ctrl));

	tmp->range_start = Start;
	tmp->range_end = End;
	if (End != -1.0) tmp->flags |= RTP_HAS_RANGE;

	if (force_bcast) tmp->flags |= RTP_FORCE_BROADCAST;

	if (is_migration) {
		tmp->current_start = (Double) CurrentTime;
		tmp->check_rtp_time = RTP_SET_TIME_RTP;
		gf_rtp_set_info_rtp(tmp->rtp_ch, rtp_seq, rtp_time, ssrc);
		tmp->status = RTP_SessionResume;
	}

	if (rvc_predef) {
		tmp->depacketizer->sl_map.rvc_predef = rvc_predef ;
	} else if (rvc_config_att) {
		char *rvc_data=NULL;
		u32 rvc_size;
		Bool is_gz = 0;
		if (!strncmp(rvc_config_att, "data:application/rvc-config+xml", 32) && strstr(rvc_config_att, "base64") ) {
			char *data = strchr(rvc_config_att, ',');
			if (data) {
				rvc_size = (u32) strlen(data) * 3 / 4 + 1;
				rvc_data = gf_malloc(sizeof(char) * rvc_size);
				rvc_size = gf_base64_decode(data, (u32) strlen(data), rvc_data, rvc_size);
				rvc_data[rvc_size] = 0;
			}
			if (!strncmp(rvc_config_att, "data:application/rvc-config+xml+gz", 35)) is_gz = 1;
		} else if (!strnicmp(rvc_config_att, "http://", 7) || !strnicmp(rvc_config_att, "https://", 8) ) {
			char *mime;
			if (gf_dm_get_file_memory(rvc_config_att, &rvc_data, &rvc_size, &mime) == GF_OK) {
				if (mime && strstr(mime, "+gz")) is_gz = 1;
				if (mime) gf_free(mime);
			}
		}
		if (rvc_data) {
			if (is_gz) {
#ifdef GPAC_DISABLE_ZLIB
				fprintf(stderr, "Error: no zlib support - RVC not supported in RTP\n");
				return NULL;
#endif
				gf_gz_decompress_payload(rvc_data, rvc_size, &tmp->depacketizer->sl_map.rvc_config, &tmp->depacketizer->sl_map.rvc_config_size);
				gf_free(rvc_data);
			} else {
				tmp->depacketizer->sl_map.rvc_config = rvc_data;
				tmp->depacketizer->sl_map.rvc_config_size = rvc_size;
			}
		}
	}

	return tmp;
}