Example #1
0
M4Err SDP_Write(SDPInfo *sdp, char **out_str_buf)
{
	char *buf;
	SDP_FMTP *fmtp;
	char temp[50];
	SDPMedia *media;
	SDPBandwidth *bw;
	u32 buf_size, pos, i, j, k;
	SDP_RTPMap *map;
	SDPConnection *conn;
	M4Err e;
	SDPTiming *timing;
	X_Attribute *att;

	e = SDP_CheckInfo(sdp);
	if (e) return e;

	buf = malloc(SDP_WRITE_STEPALLOC);
	buf_size = SDP_WRITE_STEPALLOC;
	pos = 0;

	//v
	SDP_WRITE_ALLOC_STR("v=", 0);
	SDP_WRITE_ALLOC_INT(sdp->Version, 0, 0);
	SDP_WRITE_ALLOC_STR("\r\n", 0);
	//o
	SDP_WRITE_ALLOC_STR("o=", 0);
	SDP_WRITE_ALLOC_STR(sdp->o_username, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_session_id, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_version, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_net_type, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_add_type, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_address, 0);
	SDP_WRITE_ALLOC_STR("\r\n", 0);
	//s
	TEST_SDP_WRITE_SINGLE("s=", sdp->s_session_name, 0);
	//i
	TEST_SDP_WRITE_SINGLE("i=", sdp->i_description, 0);
	//u
	TEST_SDP_WRITE_SINGLE("u=", sdp->u_uri, 0);
	//e
	TEST_SDP_WRITE_SINGLE("e=", sdp->e_email, 0);
	//p
	TEST_SDP_WRITE_SINGLE("p=", sdp->p_phone, 0);
	//c
	SDP_WRITE_CONN(sdp->c_connection);
	//b
	for (i=0; i<ChainGetCount(sdp->b_bandwidth); i++) {
		bw = ChainGetEntry(sdp->b_bandwidth, i);
		SDP_WRITE_ALLOC_STR("b=", 0);
		SDP_WRITE_ALLOC_STR(bw->name, 0);
		SDP_WRITE_ALLOC_STR(":", 0);
		SDP_WRITE_ALLOC_INT(bw->value, 0, 0);
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}
	//t+r+z
	for (i=0; i<ChainGetCount(sdp->Timing); i++) {
		timing = ChainGetEntry(sdp->Timing, i);
		if (timing->NbRepeatOffsets > SDP_MAX_TIMEOFFSET) timing->NbRepeatOffsets = SDP_MAX_TIMEOFFSET;
		if (timing->NbZoneOffsets > SDP_MAX_TIMEOFFSET) timing->NbZoneOffsets = SDP_MAX_TIMEOFFSET;
		//t
		SDP_WRITE_ALLOC_STR("t=", 0);
		SDP_WRITE_ALLOC_INT(timing->StartTime, 1, 0);
		SDP_WRITE_ALLOC_INT(timing->StopTime, 0, 0);
		SDP_WRITE_ALLOC_STR("\r\n", 0);
		if (timing->NbRepeatOffsets) {
			SDP_WRITE_ALLOC_STR("r=", 0);
			SDP_WRITE_ALLOC_INT(timing->RepeatInterval, 1, 0);
			SDP_WRITE_ALLOC_INT(timing->ActiveDuration, 0, 0);
			for (j=0; j<timing->NbRepeatOffsets; j++) {
				SDP_WRITE_ALLOC_STR(" ", 0);
				SDP_WRITE_ALLOC_INT(timing->OffsetFromStart[j], 0, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		if (timing->NbZoneOffsets) {
			SDP_WRITE_ALLOC_STR("z=", 0);
			for (j=0; j<timing->NbZoneOffsets; j++) {
				SDP_WRITE_ALLOC_INT(timing->AdjustmentTime[j], 1, 0);
				if (j+1 == timing->NbRepeatOffsets) {
					SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 0, 1);
				} else {
					SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 1, 1);
				}
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
	}
	//k
	if (sdp->k_method) {
		SDP_WRITE_ALLOC_STR("k=", 0);
		SDP_WRITE_ALLOC_STR(sdp->k_method, 0);
		if (sdp->k_key) {
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_STR(sdp->k_key, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}
	//a=cat
	TEST_SDP_WRITE_SINGLE("a=cat", sdp->a_cat, 1);
	//a=keywds
	TEST_SDP_WRITE_SINGLE("a=keywds", sdp->a_keywds, 1);
	//a=tool
	TEST_SDP_WRITE_SINGLE("a=tool", sdp->a_tool, 1);
	//a=SendRecv
	switch (sdp->a_SendRecieve) {
	case 1:
		TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0);
		break;
	case 2:
		TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0);
		break;
	case 3:
		TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0);
		break;
	default:
		break;
	}
	//a=type
	TEST_SDP_WRITE_SINGLE("a=type", sdp->a_type, 1);
	//a=charset
	TEST_SDP_WRITE_SINGLE("a=charset", sdp->a_charset, 1);
	//a=sdplang
	TEST_SDP_WRITE_SINGLE("a=sdplang", sdp->a_sdplang, 1);
	//a=lang
	TEST_SDP_WRITE_SINGLE("a=lang", sdp->a_lang, 1);

	//the rest
	for (i=0; i<ChainGetCount(sdp->Attributes); i++) {
		att = ChainGetEntry(sdp->Attributes, i);
		SDP_WRITE_ALLOC_STR("a=", 0);
		SDP_WRITE_ALLOC_STR(att->Name, 0);
		if (att->Value) {
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_STR(att->Value, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}

	//now write media specific
	for (i=0; i<ChainGetCount(sdp->media_desc); i++) {
		media = ChainGetEntry(sdp->media_desc, i);

		//m=
		SDP_WRITE_ALLOC_STR("m=", 0);
		switch (media->Type) {
		case 1:
			SDP_WRITE_ALLOC_STR("video", 1);
			break;
		case 2:
			SDP_WRITE_ALLOC_STR("audio", 1);
			break;
		case 3:
			SDP_WRITE_ALLOC_STR("data", 1);
			break;
		case 4:
			SDP_WRITE_ALLOC_STR("control", 1);
			break;
		default:
			SDP_WRITE_ALLOC_STR("application", 1);
			break;
		}
		SDP_WRITE_ALLOC_INT(media->PortNumber, 0, 0);
		if (media->NumPorts >= 2) {
			SDP_WRITE_ALLOC_STR("/", 0);
			SDP_WRITE_ALLOC_INT(media->NumPorts, 1, 0);
		} else {
			SDP_WRITE_ALLOC_STR(" ", 0);
		}
		SDP_WRITE_ALLOC_STR(media->Profile, 1);
		SDP_WRITE_ALLOC_STR(media->fmt_list, 0);

		for (j=0;j<ChainGetCount(media->RTPMaps); j++) {
			map = ChainGetEntry(media->RTPMaps, j);
			SDP_WRITE_ALLOC_STR(" ", 0);
			SDP_WRITE_ALLOC_INT(map->PayloadType, 0, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);

		//c=
		for (j=0; j<ChainGetCount(media->Connections); j++) {
			conn = ChainGetEntry(media->Connections, j);
			SDP_WRITE_CONN(conn);
		}

		//k=
		if (media->k_method) {
			SDP_WRITE_ALLOC_STR("k=", 0);
			SDP_WRITE_ALLOC_STR(media->k_method, 0);
			if (media->k_key) {
				SDP_WRITE_ALLOC_STR(":", 0);
				SDP_WRITE_ALLOC_STR(media->k_key, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//b
		for (j=0; j<ChainGetCount(media->Bandwidths); j++) {
			bw = ChainGetEntry(media->Bandwidths, j);
			SDP_WRITE_ALLOC_STR("b=", 0);
			SDP_WRITE_ALLOC_STR(bw->name, 0);
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_INT(bw->value, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}

		//a=rtpmap
		for (j=0; j<ChainGetCount(media->RTPMaps); j++) {
			map = ChainGetEntry(media->RTPMaps, j);

			SDP_WRITE_ALLOC_STR("a=rtpmap", 0);
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_INT(map->PayloadType, 1, 0);
			SDP_WRITE_ALLOC_STR(map->payload_name, 0);
			SDP_WRITE_ALLOC_STR("/", 0);
			SDP_WRITE_ALLOC_INT(map->ClockRate, 0, 0);
			if (map->AudioChannels > 1) {
				SDP_WRITE_ALLOC_STR("/", 0);
				SDP_WRITE_ALLOC_INT(map->AudioChannels, 0, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=fmtp
		for (j=0; j<ChainGetCount(media->FMTP); j++) {
			fmtp = ChainGetEntry(media->FMTP, j);
			SDP_WRITE_ALLOC_STR("a=fmtp:", 0);
			SDP_WRITE_ALLOC_INT(fmtp->PayloadType, 1 , 0);
			for (k=0; k<ChainGetCount(fmtp->Attributes); k++) {
				if (k) SDP_WRITE_ALLOC_STR(";", 0);

				att = ChainGetEntry(fmtp->Attributes, k);
				SDP_WRITE_ALLOC_STR(att->Name, 0);
				if (att->Value) {
					SDP_WRITE_ALLOC_STR("=", 0);
					SDP_WRITE_ALLOC_STR(att->Value, 0);
				}
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=ptime
		if (media->PacketTime) {
			SDP_WRITE_ALLOC_STR("a=ptime:", 0);
			SDP_WRITE_ALLOC_INT(media->PacketTime, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=FrameRate
		if (media->Type == 1 && media->FrameRate) {
			SDP_WRITE_ALLOC_STR("a=framerate:", 0);
			SDP_WRITE_ALLOC_FLOAT(media->FrameRate, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=SendRecv
		switch (media->SendRecieve) {
		case 1:
			TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0);
			break;
		case 2:
			TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0);
			break;
		case 3:
			TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0);
			break;
		default:
			break;
		}
		//a=orient
		TEST_SDP_WRITE_SINGLE("a=orient", media->orientation, 1);
		//a=sdplang
		TEST_SDP_WRITE_SINGLE("a=sdplang", media->sdplang, 1);
		//a=lang
		TEST_SDP_WRITE_SINGLE("a=lang", media->lang, 1);
		//a=quality
		if (media->Quality >= 0) {
			SDP_WRITE_ALLOC_STR("a=quality:", 0);
			SDP_WRITE_ALLOC_INT(media->Quality, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}		
		//the rest
		for (j=0; j<ChainGetCount(media->Attributes); j++) {
			att = ChainGetEntry(media->Attributes, j);
			SDP_WRITE_ALLOC_STR("a=", 0);
			SDP_WRITE_ALLOC_STR(att->Name, 0);
			if (att->Value) {
				SDP_WRITE_ALLOC_STR(":", 0);
				SDP_WRITE_ALLOC_STR(att->Value, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
	}

	//finally realloc
	//finall NULL char
	pos += 1;
	buf = realloc(buf, pos);
	*out_str_buf = buf;
	return M4OK;
}	
Example #2
0
GF_EXPORT
GF_Err gf_sdp_info_write(GF_SDPInfo *sdp, char **out_str_buf)
{
	char *buf;
	GF_SDP_FMTP *fmtp;
	char temp[50];
	GF_SDPMedia *media;
	GF_SDPBandwidth *bw;
	u32 buf_size, pos, i, j, k;
	GF_RTPMap *map;
	GF_SDPConnection *conn;
	GF_Err e;
	GF_SDPTiming *timing;
	GF_X_Attribute *att;

	e = gf_sdp_info_check(sdp);
	if (e) return e;

	buf = (char *)gf_malloc(SDP_WRITE_STEPALLOC);
	buf_size = SDP_WRITE_STEPALLOC;
	pos = 0;

	//v
	SDP_WRITE_ALLOC_STR("v=", 0);
	SDP_WRITE_ALLOC_INT(sdp->Version, 0, 0);
	SDP_WRITE_ALLOC_STR("\r\n", 0);
	//o
	SDP_WRITE_ALLOC_STR("o=", 0);
	SDP_WRITE_ALLOC_STR(sdp->o_username, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_session_id, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_version, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_net_type, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_add_type, 1);
	SDP_WRITE_ALLOC_STR(sdp->o_address, 0);
	SDP_WRITE_ALLOC_STR("\r\n", 0);
	//s
	TEST_SDP_WRITE_SINGLE("s=", sdp->s_session_name, 0);
	//i
	TEST_SDP_WRITE_SINGLE("i=", sdp->i_description, 0);
	//u
	TEST_SDP_WRITE_SINGLE("u=", sdp->u_uri, 0);
	//e
	TEST_SDP_WRITE_SINGLE("e=", sdp->e_email, 0);
	//p
	TEST_SDP_WRITE_SINGLE("p=", sdp->p_phone, 0);
	//c
	SDP_WRITE_CONN(sdp->c_connection);
	//b
	i=0;
	while ((bw = (GF_SDPBandwidth*)gf_list_enum(sdp->b_bandwidth, &i))) {
		SDP_WRITE_ALLOC_STR("b=", 0);
		SDP_WRITE_ALLOC_STR(bw->name, 0);
		SDP_WRITE_ALLOC_STR(":", 0);
		SDP_WRITE_ALLOC_INT(bw->value, 0, 0);
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}
	//t+r+z
	i=0;
	while ((timing = (GF_SDPTiming*)gf_list_enum(sdp->Timing, &i))) {
		if (timing->NbRepeatOffsets > GF_SDP_MAX_TIMEOFFSET) timing->NbRepeatOffsets = GF_SDP_MAX_TIMEOFFSET;
		if (timing->NbZoneOffsets > GF_SDP_MAX_TIMEOFFSET) timing->NbZoneOffsets = GF_SDP_MAX_TIMEOFFSET;
		//t
		SDP_WRITE_ALLOC_STR("t=", 0);
		SDP_WRITE_ALLOC_INT(timing->StartTime, 1, 0);
		SDP_WRITE_ALLOC_INT(timing->StopTime, 0, 0);
		SDP_WRITE_ALLOC_STR("\r\n", 0);
		if (timing->NbRepeatOffsets) {
			SDP_WRITE_ALLOC_STR("r=", 0);
			SDP_WRITE_ALLOC_INT(timing->RepeatInterval, 1, 0);
			SDP_WRITE_ALLOC_INT(timing->ActiveDuration, 0, 0);
			for (j=0; j<timing->NbRepeatOffsets; j++) {
				SDP_WRITE_ALLOC_STR(" ", 0);
				SDP_WRITE_ALLOC_INT(timing->OffsetFromStart[j], 0, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		if (timing->NbZoneOffsets) {
			SDP_WRITE_ALLOC_STR("z=", 0);
			for (j=0; j<timing->NbZoneOffsets; j++) {
				SDP_WRITE_ALLOC_INT(timing->AdjustmentTime[j], 1, 0);
				if (j+1 == timing->NbRepeatOffsets) {
					SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 0, 1);
				} else {
					SDP_WRITE_ALLOC_INT(timing->AdjustmentOffset[j], 1, 1);
				}
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
	}
	//k
	if (sdp->k_method) {
		SDP_WRITE_ALLOC_STR("k=", 0);
		SDP_WRITE_ALLOC_STR(sdp->k_method, 0);
		if (sdp->k_key) {
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_STR(sdp->k_key, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}
	//a=cat
	TEST_SDP_WRITE_SINGLE("a=cat", sdp->a_cat, 1);
	//a=keywds
	TEST_SDP_WRITE_SINGLE("a=keywds", sdp->a_keywds, 1);
	//a=tool
	TEST_SDP_WRITE_SINGLE("a=tool", sdp->a_tool, 1);
	//a=SendRecv
	switch (sdp->a_SendReceive) {
	case 1:
		TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0);
		break;
	case 2:
		TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0);
		break;
	case 3:
		TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0);
		break;
	default:
		break;
	}
	//a=type
	TEST_SDP_WRITE_SINGLE("a=type", sdp->a_type, 1);
	//a=charset
	TEST_SDP_WRITE_SINGLE("a=charset", sdp->a_charset, 1);
	//a=sdplang
	TEST_SDP_WRITE_SINGLE("a=sdplang", sdp->a_sdplang, 1);
	//a=lang
	TEST_SDP_WRITE_SINGLE("a=lang", sdp->a_lang, 1);

	//the rest
	i=0;
	while ((att = (GF_X_Attribute*)gf_list_enum(sdp->Attributes, &i))) {
		SDP_WRITE_ALLOC_STR("a=", 0);
		SDP_WRITE_ALLOC_STR(att->Name, 0);
		if (att->Value) {
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_STR(att->Value, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);
	}

	//now write media specific
	i=0;
	while ((media = (GF_SDPMedia*)gf_list_enum(sdp->media_desc, &i))) {
		//m=
		SDP_WRITE_ALLOC_STR("m=", 0);
		switch (media->Type) {
		case 1:
			SDP_WRITE_ALLOC_STR("video", 1);
			break;
		case 2:
			SDP_WRITE_ALLOC_STR("audio", 1);
			break;
		case 3:
			SDP_WRITE_ALLOC_STR("data", 1);
			break;
		case 4:
			SDP_WRITE_ALLOC_STR("control", 1);
			break;
		default:
			SDP_WRITE_ALLOC_STR("application", 1);
			break;
		}
		SDP_WRITE_ALLOC_INT(media->PortNumber, 0, 0);
		if (media->NumPorts >= 2) {
			SDP_WRITE_ALLOC_STR("/", 0);
			SDP_WRITE_ALLOC_INT(media->NumPorts, 1, 0);
		} else {
			SDP_WRITE_ALLOC_STR(" ", 0);
		}
		SDP_WRITE_ALLOC_STR(media->Profile, 1);
		SDP_WRITE_ALLOC_STR(media->fmt_list, 0);

		j=0;
		while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) {
			SDP_WRITE_ALLOC_STR(" ", 0);
			SDP_WRITE_ALLOC_INT(map->PayloadType, 0, 0);
		}
		SDP_WRITE_ALLOC_STR("\r\n", 0);

		//c=
		j=0;
		while ((conn = (GF_SDPConnection*)gf_list_enum(media->Connections, &j))) {
			SDP_WRITE_CONN(conn);
		}

		//k=
		if (media->k_method) {
			SDP_WRITE_ALLOC_STR("k=", 0);
			SDP_WRITE_ALLOC_STR(media->k_method, 0);
			if (media->k_key) {
				SDP_WRITE_ALLOC_STR(":", 0);
				SDP_WRITE_ALLOC_STR(media->k_key, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//b
		j=0;
		while ((bw = (GF_SDPBandwidth*)gf_list_enum(media->Bandwidths, &j))) {
			SDP_WRITE_ALLOC_STR("b=", 0);
			SDP_WRITE_ALLOC_STR(bw->name, 0);
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_INT(bw->value, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}

		//a=rtpmap
		j=0;
		while ((map = (GF_RTPMap*)gf_list_enum(media->RTPMaps, &j))) {

			SDP_WRITE_ALLOC_STR("a=rtpmap", 0);
			SDP_WRITE_ALLOC_STR(":", 0);
			SDP_WRITE_ALLOC_INT(map->PayloadType, 1, 0);
			SDP_WRITE_ALLOC_STR(map->payload_name, 0);
			SDP_WRITE_ALLOC_STR("/", 0);
			SDP_WRITE_ALLOC_INT(map->ClockRate, 0, 0);
			if (map->AudioChannels > 1) {
				SDP_WRITE_ALLOC_STR("/", 0);
				SDP_WRITE_ALLOC_INT(map->AudioChannels, 0, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=fmtp
		j=0;
		while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &j))) {
			SDP_WRITE_ALLOC_STR("a=fmtp:", 0);
			SDP_WRITE_ALLOC_INT(fmtp->PayloadType, 1 , 0);
			k=0;
			while ((att = (GF_X_Attribute*)gf_list_enum(fmtp->Attributes, &k)) ) {
				if (k>1) SDP_WRITE_ALLOC_STR(";", 0);
				SDP_WRITE_ALLOC_STR(att->Name, 0);
				if (att->Value) {
					SDP_WRITE_ALLOC_STR("=", 0);
					SDP_WRITE_ALLOC_STR(att->Value, 0);
				}
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=ptime
		if (media->PacketTime) {
			SDP_WRITE_ALLOC_STR("a=ptime:", 0);
			SDP_WRITE_ALLOC_INT(media->PacketTime, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=FrameRate
		if (media->Type == 1 && media->FrameRate) {
			SDP_WRITE_ALLOC_STR("a=framerate:", 0);
			SDP_WRITE_ALLOC_FLOAT(media->FrameRate, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
		//a=SendRecv
		switch (media->SendReceive) {
		case 1:
			TEST_SDP_WRITE_SINGLE("a=", "recvonly", 0);
			break;
		case 2:
			TEST_SDP_WRITE_SINGLE("a=", "sendonly", 0);
			break;
		case 3:
			TEST_SDP_WRITE_SINGLE("a=", "sendrecv", 0);
			break;
		default:
			break;
		}
		//a=orient
		TEST_SDP_WRITE_SINGLE("a=orient", media->orientation, 1);
		//a=sdplang
		TEST_SDP_WRITE_SINGLE("a=sdplang", media->sdplang, 1);
		//a=lang
		TEST_SDP_WRITE_SINGLE("a=lang", media->lang, 1);
		//a=quality
		if (media->Quality >= 0) {
			SDP_WRITE_ALLOC_STR("a=quality:", 0);
			SDP_WRITE_ALLOC_INT(media->Quality, 0, 0);
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}		
		//the rest
		j=0;
		while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &j))) {
			SDP_WRITE_ALLOC_STR("a=", 0);
			SDP_WRITE_ALLOC_STR(att->Name, 0);
			if (att->Value) {
				SDP_WRITE_ALLOC_STR(":", 0);
				SDP_WRITE_ALLOC_STR(att->Value, 0);
			}
			SDP_WRITE_ALLOC_STR("\r\n", 0);
		}
	}

	//finally gf_realloc
	//finall NULL char
	pos += 1;
	buf = (char *)gf_realloc(buf, pos);
	*out_str_buf = buf;
	return GF_OK;
}