[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