[xiph-commits] r10363 - trunk/xiph-rtp

lu_zero at svn.xiph.org lu_zero at svn.xiph.org
Thu Nov 10 15:47:13 PST 2005


Author: lu_zero
Date: 2005-11-10 15:47:09 -0800 (Thu, 10 Nov 2005)
New Revision: 10363

Modified:
   trunk/xiph-rtp/xiph_rtp.c
   trunk/xiph-rtp/xiph_rtp.h
Log:
common function set and context struct hopefully completed

Modified: trunk/xiph-rtp/xiph_rtp.c
===================================================================
--- trunk/xiph-rtp/xiph_rtp.c	2005-11-10 06:36:11 UTC (rev 10362)
+++ trunk/xiph-rtp/xiph_rtp.c	2005-11-10 23:47:09 UTC (rev 10363)
@@ -46,82 +46,354 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include <xiph_rtp.h>
+#include "xiph_rtp.h"
 
 
+void progressmarker (int type)
+{
+	static int outmarkpos=0;
+	FILE *out=stderr;
+	
+	switch (type) {
+		case 0:
+			fprintf (out, "."); /* normal */
+		break;
+		case 1:
+			fprintf (out, "<"); /* start fragment */
+		break;
+
+		case 2:
+			fprintf (out, "+"); /* middle fragment */
+		break;
+
+		case 3:
+			fprintf (out, ">"); /* end fragment */
+		break;
+#if 0
+		case 4:
+			fprintf (stdout, "b"); /* setup header */
+		break;
+
+		case 5:
+			fprintf (stdout, "p"); /* packed */
+		break;
+
+		case 6:
+			fprintf (stdout, "c"); /* info header */
+		break;
+	
+#endif
+		default:
+		break;
+	}
+
+	fflush (NULL);
+	
+	if (outmarkpos == 70) {
+		fprintf (out, "\n");
+		outmarkpos = 0;
+	} else 
+		outmarkpos++;
+}
+
+
+
 //FIXME remove the exit
 int createsocket (xiph_rtp_t *xr, char *addr, unsigned int port, 
-		  unsigned char TTL){
-    int socket, ret;
-    int optval = 0;
-    struct sockaddr_in sin;
-    rtp_headers_t *headers= &xr->headers;
-    
-    
+		  unsigned char TTL)
+{
+	int ret;
+	int optval = 0;
+	struct sockaddr_in sin;
+	rtp_headers_t *headers= &xr->headers;
 
-/*===========================================================================*/
-/*  Init RTP headers                                                         */
-/*===========================================================================*/
+/*  Init RTP headers  */
 
 /*  Sets v=2, p=0, x=0, cc=0  */
-    headers -> flags1 = 0x80;
+	headers -> flags1 = 0x80;
 
 /*  Sets m=0, pt=96  */
-    headers -> flags2 = 0x60;
+	headers -> flags2 = 0x60;
 
-    headers -> sequence = htonl (rand () & 65535);
-    headers -> timestamp = htonl (rand ());
-    headers -> ssrc = htonl (rand ());
+	headers -> sequence = htonl (rand () & 65535);
+	headers -> timestamp = htonl (rand ());
+	headers -> ssrc = htonl (rand ());
 
-/*===========================================================================*/
-/*  Create socket                                                            */
-/*===========================================================================*/
+/*  Create socket  */
 
-    socket = socket (AF_INET, SOCK_DGRAM, 0);
+	xr->socket = socket(AF_INET, SOCK_DGRAM, 0);
 
-    if (socket < 0) {
-        fprintf (stderr, "Socket creation failed.\n");
-        exit (1);
-    }
+	if (xr->socket < 0) {
+		fprintf (stderr, "Socket creation failed.\n");
+		exit (1);
+	}
 
-    xr->rtpsock.sin_family = sin.sin_family = AF_INET;
-    xr->rtpsock.sin_port = sin.sin_port = htons (port);
-    xr->rtpsock.sin_addr.s_addr = inet_addr (addr);
+	xr->rtpsock.sin_family = sin.sin_family = AF_INET;
+	xr->rtpsock.sin_port = sin.sin_port = htons (port);
+	xr->rtpsock.sin_addr.s_addr = inet_addr (addr);
 
-    ret = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
+	ret = setsockopt (xr->socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
 
-    if (ret < 0) {
-        fprintf (stderr, "setsockopt SO_REUSEADDR error\n");
-        exit (1);
-    }
+	if (ret < 0) {
+		fprintf (stderr, "setsockopt SO_REUSEADDR error\n");
+		exit (1);
+	}
 
+/*  Set multicast parameters */
+
+	if (IN_MULTICAST (ntohl (xr->rtpsock.sin_addr.s_addr))) {
+
+		ret = setsockopt (xr->socket, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof (char));
+
+		if (ret < 0) {
+			fprintf (stderr, "Multicast setsockopt TTL failed.\n");
+			exit (1);
+		}
+
+		optval = 1; 
+
+		ret = setsockopt (xr->socket, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof (char));
+
+		if (ret < 0) {
+			fprintf (stderr, "Multicast setsockopt LOOP failed.\n");
+			exit (1);
+		}
+	} 
+
+	return xr->socket;
+}
+
+int sendrtp (xiph_rtp_t *xr, const void *data, int len)
+{
+	int ret;
+	char *outbuffer;
+
+		outbuffer = malloc (sizeof (rtp_headers_t) + len);
+	
+	memcpy (outbuffer,  &xr->headers, sizeof (rtp_headers_t));
+	memcpy (outbuffer + sizeof (rtp_headers_t), data, len);
+	
+	ret = sendto (xr->socket, outbuffer, sizeof (rtp_headers_t) + len,
+			0, (struct sockaddr *) &xr->rtpsock,
+			sizeof (struct sockaddr_in));
+	
+	free (outbuffer);
+	return (ret);
+}
+
+
+//FIXME max_payload should stay somewhere else
+void creatertp (xiph_rtp_t *xr, unsigned char* vorbdata, int length,
+		long timestamp, int type)
+{
+	int sleeptime, frag, position = 0;
+	unsigned short framesize;
+	unsigned char *packet;
+
+	const unsigned int max_payload = 1000;
+
+/*  Set sleeptime value based on timestamp */
+
+	if (type)
+		sleeptime = 300; //  ((1 / (float) bitrate) * 1000000);
+	else
+		sleeptime = timestamp;
+
+/*  Frame fragmentation */
+
+	if (length > max_payload) {
+		frag = 1;
+		while (length > max_payload) {		
+		/*  Set Vorbis header flags  */
+			xr->bitfield.frag_type = frag;
+			xr->bitfield.data_type = type;
+			xr->bitfield.pkts = 0;
+
+			framesize = max_payload;
+
+			packet = malloc (framesize + 4 + 2);
+
+			makeheader (xr, packet, framesize + 2 + 4);
+		/* write 16-bit network order fragment length */
+			packet[4]=(framesize&0xff00)>>8;
+			packet[5]=framesize&0xff;
+			memcpy (packet + 4 + 2, vorbdata + position, framesize);
+
+			/*  Swap RTP headers from host to network order  */
+			xr->headers.sequence = htons (xr->headers.sequence);
+
+			sendrtp (xr, packet, framesize + 4 + 2);
+
+			/*  Swap headers back to host order  */
+			xr->headers.sequence = ntohs (xr->headers.sequence);
+
+			length -= max_payload;
+			position += max_payload;
+			frag = 2;
+
+			xr->headers.sequence = xr->headers.sequence + 1;
+
+			progressmarker (1);
+
+			free (packet);
+		}
+
+		/*  Set Vorbis header flags  */
+		xr->bitfield.frag_type = 3;
+		xr->bitfield.data_type = type;
+		xr->bitfield.pkts = 0;
+
+		framesize = length;
+
+		packet = malloc (length + 4 + 2);
+
+		makeheader (xr, packet, length + 4 + 2);
+		packet[4]=(framesize&0xff00)>>8;
+		packet[5]=framesize&0xff;
+		memcpy (packet + 4 + 2, vorbdata + position, length);
+
+		/*  Swap RTP headers from host to network order  */
+		xr->headers.sequence = htons (xr->headers.sequence);
+		xr->headers.timestamp = htonl (xr->headers.timestamp);
+
+		sendrtp (xr, packet, length + 4 + 2);
+
+		/*  Swap headers back to host order  */
+		xr->headers.sequence = htons (xr->headers.sequence);
+		xr->headers.timestamp = ntohl (xr->headers.timestamp);
+
+		/*  Increment RTP headers  */
+		xr->headers.sequence++;
+		xr->headers.timestamp += sleeptime;
+
+		progressmarker (2);
+
+		free (packet);
+		return;
+	}
+
+/*  Frame packing.  Used only for type 0 packets (raw Vorbis data) */
+
+	if (length < max_payload && type == 0) {
+		framestack_t *fs = &xr->fs;
+
+		if (length + fs->stacksize < max_payload && fs->stackcount < 15) {
+		fs->framestack = realloc (fs->framestack, (fs->stacksize + (length + 2)));	
+		fs->framestack[fs->stacksize++]= (length&0xff00)>>8;
+		fs->framestack[fs->stacksize++]= length&0xff;
+		
+		memcpy (fs->framestack + (fs->stacksize), vorbdata, length);
+		fs->stackcount++;
+		fs->stacksize += (length);
+		}
+
+	/* todo: we also need to be able to flush this at end-of-stream */
+
+		if (length + fs->stacksize > max_payload || fs->stackcount >= 15) {
+
+			/*  Set Vorbis header flags  */
+			xr->bitfield.frag_type = 0;
+			xr->bitfield.data_type = 0;
+			xr->bitfield.pkts = fs->stackcount;
+
+			packet = malloc (fs->stacksize + 4);
+
+			makeheader (xr, packet, fs->stacksize + 4);
+			memcpy (packet + 4, fs->framestack, fs->stacksize);
+
+			/*  Swap RTP headers from host to network order  */
+			xr->headers.sequence = htons (xr->headers.sequence);
+			xr->headers.timestamp = htonl (xr->headers.timestamp);
+
+			sendrtp (xr, packet, fs->stacksize + 4);
+
+			/*  Swap headers back to host order  */
+			xr->headers.sequence = htons (xr->headers.sequence);
+			xr->headers.timestamp = ntohl (xr->headers.timestamp);
+
+			if (fs->stackcount == 1) 
+				progressmarker (0);
+			else
+				progressmarker (5);
+
+			usleep (sleeptime); /* WRONG */
+
+			xr->headers.sequence++;
+			xr->headers.timestamp += sleeptime;
+
+			fs->stacksize = 0;
+			fs->stackcount = 0;
+
+			free (packet);
+		}   
+		return;
+	} 
+
 /*===========================================================================*/
-/*  Set multicast parameters                                                 */
+/*  Send header packets (under max_payload octets) - No Packing			  */
 /*===========================================================================*/
 
-    if (IN_MULTICAST (ntohl (xr->rtpsock.sin_addr.s_addr))) {
+	else if (length < max_payload) {
 
-        ret = setsockopt (socket, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof (char));
+		/*  Set Vorbis header flags  */
+		xr->bitfield.frag_type = 0;
+		xr->bitfield.data_type = type;
+		xr->bitfield.pkts = 1;
 
-        if (ret < 0) {
-            fprintf (stderr, "Multicast setsockopt TTL failed.\n");
-            exit (1);
-        }
+		framesize = (unsigned char) length;
 
-        optval = 1; 
+		packet = malloc (length + 4 + 2);
 
-        ret = setsockopt (socket, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof (char));
+		makeheader (xr, packet, length + 4 + 2);
 
-        if (ret < 0) {
-            fprintf (stderr, "Multicast setsockopt LOOP failed.\n");
-            exit (1);
-        }
-    }
+	packet[4]=(length&0xff00)>>8;
+	packet[5]=length&0xff;
 
-    //FIXME
-    //rx->socket = socket; 
+		memcpy (packet + 4 + 2, vorbdata, length);
 
-    return socket;
+		/*  Swap RTP headers from host to network order  */
+		xr->headers.sequence = htons (xr->headers.sequence);
+		xr->headers.timestamp = htonl (xr->headers.timestamp);
+
+		sendrtp (xr, packet, length + 4 + 2);
+
+		/*  Swap headers back to host order  */
+		xr->headers.sequence = htons (xr->headers.sequence);
+		xr->headers.timestamp = ntohl (xr->headers.timestamp);
+
+	/* WRONG. We need to sleep something like 1/2 the time to the
+	   next packet. The caller should probably handle this. */
+		sleeptime = timestamp;
+		usleep (sleeptime);
+
+		xr->headers.sequence++;
+		xr->headers.timestamp += sleeptime;
+
+		free (packet);
+	}			
 }
+	
+int makeheader (xiph_rtp_t *xr, unsigned char *packet, int length)
+{
+	if (xr->codec == 3) return 0; //Speex has no header
+	
+	/* Vorbis and Theora header */
+	if (length < sizeof(header_bitfield_t)) return -1;
+	
+	printf( "\tident %06x, frag type %d,"
+		" data type %d, pkts %02d, size %d\n", xr->bitfield.cbident,
+		xr->bitfield.frag_type, xr->bitfield.data_type,
+		xr->bitfield.pkts, length);
 
+	packet[0] = (xr->bitfield.cbident&0xff0000)>>16;
+	packet[1] = (xr->bitfield.cbident&0xff00)>>8;
+	packet[2] = xr->bitfield.cbident&0xff;
+	
+	packet[3] = (xr->bitfield.frag_type) << 6;
+	packet[3] |= (xr->bitfield.data_type) << 4;
+	packet[3] |= (xr->bitfield.pkts) & 0xf;
+	
+	return 0;
 
+}
+

Modified: trunk/xiph-rtp/xiph_rtp.h
===================================================================
--- trunk/xiph-rtp/xiph_rtp.h	2005-11-10 06:36:11 UTC (rev 10362)
+++ trunk/xiph-rtp/xiph_rtp.h	2005-11-10 23:47:09 UTC (rev 10363)
@@ -62,6 +62,13 @@
 } rtp_headers_t;
 
 
+typedef struct framestack {
+	int stacksize;
+	int stackcount;
+	unsigned char* framestack;
+} framestack_t;
+
+
 /**
  * Context structure for rtp transmission
  */
@@ -73,12 +80,16 @@
 	int socket;
 	header_bitfield_t bitfield;
 	rtp_headers_t headers;
+	/* rtp related*/
+	framestack_t fs;
 	/* stream related */
 	ogg_sync_state oy;
 	ogg_stream_state os;
 	ogg_page og;
 	ogg_packet op;
 	ogg_packet header[3];
+	/* codec generic */
+	int codec; // 0 = vorbis, 1 = theora, 2 =speex
 	/* codec specific (vorbis)*/
 	vorbis_info vi; 
 	vorbis_comment vc;
@@ -91,12 +102,13 @@
 	/* codec specific (speex) */
 	//FIXME
 	
-} xiph_rtp_t
+} xiph_rtp_t;
 
 int createsocket (xiph_rtp_t *xr, char *addr, unsigned int port,
 		  unsigned char TTL);
 
-void creatertp (xiph_rtp_t *xr, unsigned char* vorbdata, int length, long timestamp, int type);
+void creatertp (xiph_rtp_t *xr, unsigned char* vorbdata, int length,
+		long timestamp, int type);
 
 int sendrtp (xiph_rtp_t *xr, const void *data, int len);
 



More information about the commits mailing list