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

giles at motherfish-iii.xiph.org giles at motherfish-iii.xiph.org
Sun Feb 6 20:45:55 PST 2005


Author: giles
Date: 2005-02-06 20:45:55 -0800 (Sun, 06 Feb 2005)
New Revision: 8844

Added:
   trunk/xiph-rtp/vorbisrtp.c
Log:
Initial commit of Phil Kerr's reference implementation in progress.
This is the public version from his website published 2005 January 5.


Added: trunk/xiph-rtp/vorbisrtp.c
===================================================================
--- trunk/xiph-rtp/vorbisrtp.c	2005-02-07 04:00:03 UTC (rev 8843)
+++ trunk/xiph-rtp/vorbisrtp.c	2005-02-07 04:45:55 UTC (rev 8844)
@@ -0,0 +1,787 @@
+/*****************************************************************************
+||  File: Vorbis RTP Server                                                 
+||  Author: Phil Kerr                                                        
+||  Date: 05/01/2005
+||  Platform: Linux
+||
+||  Copyright (c) 2005, Fluendo / Xiph.Org
+||
+||  Redistribution and use in source and binary forms, with or without 
+||  modification, are permitted provided that the following conditions are met:
+||
+||  * Redistributions of source code must retain the above copyright notice, 
+||    this list of conditions and the following disclaimer.
+||
+||  * Redistributions in binary form must reproduce the above copyright notice, 
+||    this list of conditions and the following disclaimer in the documentation 
+||    and/or other materials provided with the distribution.
+||
+||  * Neither the name of the Xiph.Org nor the names of its contributors may 
+||    be used to endorse or promote products derived from this software without 
+||    specific prior written permission.
+||
+||  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+||  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
+||  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+||  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
+||  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+||  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+||  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+||  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+||  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+||  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+||  THE POSSIBILITY OF SUCH DAMAGE.
+||
+||*****************************************************************************
+||
+||  Compile:  gcc vorbisrtp.c -o vorbisrtp -lvorbis -logg -fpack-struct -Wall
+||
+||  $Id:$                                                       
+||                  
+||****************************************************************************/
+/*  General includes                                                         */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+/*****************************************************************************/
+/*  Vorbis includes                                                          */
+/*****************************************************************************/
+
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+/*****************************************************************************/
+/*  Network includes                                                         */
+/*****************************************************************************/
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/*****************************************************************************/
+/*  Data structs and variables                                               */
+/*****************************************************************************/
+
+ogg_int16_t convbuffer [4096];
+int convsize = 4096;
+
+struct sockaddr_in rtpsock;
+int rtpsocket;
+
+/*****************************************************************************/
+/*  Vorbis packet header                                                     */
+/*****************************************************************************/
+
+struct VorbisBitfields {
+    unsigned int cbident:32;
+    int continuation:1;
+    int fragment:1;
+    int type:2;
+    int pkts:4;
+} VorbisBitfields;
+
+/*****************************************************************************/
+/*  Vorbis configuration packet                                              */
+/*****************************************************************************/
+
+struct VorbisConfig {
+    unsigned int bsz0:4;
+    unsigned int bsz1:4;
+    unsigned char channels;
+    unsigned long version:32;
+    unsigned long samplerate:32;
+    unsigned long bitratemax:32;
+    unsigned long bitratenom:32;
+    unsigned long bitratemin:32;
+} VorbisConfig;
+
+/*****************************************************************************/
+/*  RTP header                                                               */
+/*****************************************************************************/
+
+struct RTPHeaders {
+/*  v, p, x, cc flags  */
+    unsigned int flags1:8;
+
+/*  m, pt flags  */
+    unsigned int flags2:8;
+
+    unsigned int sequence:16;
+    unsigned int timestamp:32;
+    unsigned int ssrc:32;
+} RTPHeaders;
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+void progressmarker (int type);
+unsigned int crc32 (int length, unsigned char *crcdata);
+int createsocket (struct RTPHeaders *RTPHeaders, struct sockaddr_in *sockAddr, char *addr, unsigned int port, unsigned char TTL);
+void creatertp (unsigned char* vorbdata, int length, int bitrate, struct VorbisBitfields *vorbheader, int type);
+int sendrtp (struct RTPHeaders *RTPHeaders, int fd, struct sockaddr_in *sockAddr, const void *data, int len);
+void configpacket (struct VorbisConfig *Config, int bsz0, int bsz1, vorbis_info vi);
+
+/*****************************************************************************/
+/*  Calculate CRC32                                                          */
+/*****************************************************************************/
+
+unsigned int crc32 (int length, unsigned char *crcdata) 
+{
+    int index, loop;
+    unsigned int byte, crc, mask;
+
+    index = 0;
+    crc = 0xFFFFFFFF;
+
+    while (index < length) {
+        byte = crcdata [index];
+        crc = crc ^ byte;
+
+        for (loop = 7; loop >= 0; loop--) {
+            mask = -(crc & 1);
+            crc = (crc >> 1) ^ (0xEDB88320 & mask);
+        }
+        index++;
+    }
+    return ~crc;
+}
+
+/*****************************************************************************/
+/*  Print progress marker                                                    */
+/*****************************************************************************/
+
+void progressmarker (int type)
+{
+/*===========================================================================*/
+/*  Prints output markers. 0 = normal, 1 = frag, 2 = last frag,              */
+/*  3 = comment, 4 = codebook, 5 = packed, 6 = config                        */
+/*===========================================================================*/
+
+/*  Output marker position  */
+    static int outmarkpos = 0;
+
+    switch (type) {
+        case 0:
+            fprintf (stdout, ".");
+        break;
+
+        case 1:
+            fprintf (stdout, "+");
+        break;
+
+        case 2:
+            fprintf (stdout, "|");
+        break;
+
+        case 3:
+            fprintf (stdout, "m");
+        break;
+
+        case 4:
+            fprintf (stdout, "b");
+        break;
+
+        case 5:
+            fprintf (stdout, "p");
+        break;
+
+        case 6:
+            fprintf (stdout, "c");
+        break;
+    };
+
+    fflush (NULL);
+
+    if (outmarkpos == 70) {
+        fprintf (stdout, "\n||  ");
+        outmarkpos = 0;
+    } else 
+        outmarkpos++;
+}
+
+/*****************************************************************************/
+/*  Creates and send configuration packet                                    */
+/*****************************************************************************/
+
+void configpacket (struct VorbisConfig *Config, int bsz0, int bsz1, vorbis_info vi) 
+{
+    Config -> bsz0 = bsz0;
+    Config -> bsz1 = bsz1;
+    Config -> channels = htons (vi.channels);
+    Config -> version = htonl (vi.version);
+    Config -> samplerate = htonl (vi.rate);
+    Config -> bitratemin = htonl (vi.bitrate_lower);
+    Config -> bitratenom = htonl (vi.bitrate_nominal);
+    Config -> bitratemax = htonl (vi.bitrate_upper);
+
+    creatertp ((unsigned char*) Config, 22, vi.rate, &VorbisBitfields, 1);
+    progressmarker (6);
+}
+
+/*****************************************************************************/
+/*  Creates RTP socket                                                       */
+/*****************************************************************************/
+
+int createsocket (struct RTPHeaders *RTPHeaders, struct sockaddr_in *sockAddr, char *addr, unsigned int port, unsigned char TTL)
+{
+    int RTPSocket, ret;
+    int optval = 0;
+    struct sockaddr_in sin;
+
+/*===========================================================================*/
+/*  Init RTP headers                                                         */
+/*===========================================================================*/
+
+/*  Sets v=2, p=0, x=0, cc=0  */
+    RTPHeaders -> flags1 = 0x80;
+
+/*  Sets m=0, pt=96  */
+    RTPHeaders -> flags2 = 0x60;
+
+    RTPHeaders -> sequence = htonl (rand () & 65535);
+    RTPHeaders -> timestamp = htonl (rand ());
+    RTPHeaders -> ssrc = htonl (rand ());
+
+/*===========================================================================*/
+/*  Create socket                                                            */
+/*===========================================================================*/
+
+    RTPSocket = socket (AF_INET, SOCK_DGRAM, 0);
+
+    if (RTPSocket < 0) {
+        fprintf (stderr, "Socket creation failed.\n");
+        exit (1);
+    }
+
+    sockAddr -> sin_family = sin.sin_family = AF_INET;
+    sockAddr -> sin_port = sin.sin_port = htons (port);
+    sockAddr -> sin_addr.s_addr = inet_addr (addr);
+
+    ret = setsockopt (RTPSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
+
+    if (ret < 0) {
+        fprintf (stderr, "setsockopt SO_REUSEADDR error\n");
+        exit (1);
+    }
+
+/*===========================================================================*/
+/*  Set multicast parameters                                                 */
+/*===========================================================================*/
+
+    if (IN_MULTICAST (ntohl (sockAddr -> sin_addr.s_addr))) {
+
+        ret = setsockopt (RTPSocket, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof (char));
+
+        if (ret < 0) {
+            fprintf (stderr, "Multicast setsockopt TTL failed.\n");
+            exit (1);
+        }
+
+        optval = 1; 
+
+        ret = setsockopt (RTPSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof (char));
+
+        if (ret < 0) {
+            fprintf (stderr, "Multicast setsockopt LOOP failed.\n");
+            exit (1);
+        }
+    }
+
+    return RTPSocket;
+}
+
+/*****************************************************************************/
+/*  Creates RTP packet from Vorbis frame.                                    */
+/*  Deals with fragmentation and multiple Vorbis frame RTP packets           */
+/*****************************************************************************/
+
+void creatertp (unsigned char* vorbdata, int length, int bitrate, struct VorbisBitfields *vorbheader, int type)
+{
+    int sleeptime, frag = 0, position = 0;
+    unsigned char framesize;
+    unsigned char *packet;
+
+    static int stacksize;
+    static int stackcount;
+    static unsigned char* framestack;
+
+/*===========================================================================*/
+/*  Test Codebook Ident (used for debug)                                     */
+/*===========================================================================*/
+
+    vorbheader -> cbident = htonl (0xc0deb00c);
+
+/*===========================================================================*/
+/*  Set sleeptime value                                                      */
+/*===========================================================================*/
+
+    sleeptime = ((1 / (float) bitrate) * 1000000);
+
+/*===========================================================================*/
+/*  Frame fragmentation                                                      */
+/*===========================================================================*/
+
+    if (length > 256) {
+        while (length > 256) {        
+            /*  Set Vorbis header flags  */
+            vorbheader -> continuation = 1;
+            vorbheader -> fragment = frag;
+            vorbheader -> type = type;
+            vorbheader -> pkts = 0;
+
+            packet = malloc (262);
+
+            memcpy (packet, vorbheader, 5);
+            memcpy (packet + 5, &framesize, 1);
+            memmove (packet + 6, vorbdata, 256);
+
+            /*  Swap RTP headers from host to network order  */
+            RTPHeaders.sequence = htons (RTPHeaders.sequence);
+
+            sendrtp (&RTPHeaders, rtpsocket, &rtpsock, packet, 262);
+
+            /*  Swap headers back to host order  */
+            RTPHeaders.sequence = ntohs (RTPHeaders.sequence);
+
+            length -= 256;
+            position += 256;
+            frag = 1;
+
+            RTPHeaders.sequence = RTPHeaders.sequence + 1;
+
+            progressmarker (1);
+
+            free (packet);
+        }
+
+        /*  Set Vorbis header flags  */
+        vorbheader -> continuation = 1;
+        vorbheader -> fragment = 1;
+        vorbheader -> type = type;
+        vorbheader -> pkts = 0;
+
+        framesize = (unsigned char) length;
+
+        packet = malloc (length + 6);
+
+        memcpy (packet, vorbheader, 5);
+        memcpy (packet + 5, &framesize, 1);
+        memcpy (packet + 6, vorbdata + position, length);
+
+        /*  Swap RTP headers from host to network order  */
+        RTPHeaders.sequence = htons (RTPHeaders.sequence);
+        RTPHeaders.timestamp = htonl (RTPHeaders.timestamp);
+
+        sendrtp (&RTPHeaders, rtpsocket, &rtpsock, packet, length + 6);
+
+        /*  Swap headers back to host order  */
+        RTPHeaders.sequence = htons (RTPHeaders.sequence);
+        RTPHeaders.timestamp = ntohl (RTPHeaders.timestamp);
+
+        /*  Increment RTP headers  */
+        RTPHeaders.sequence++;
+        RTPHeaders.timestamp += sleeptime;
+
+        progressmarker (2);
+
+        free (packet);
+        return;
+    }
+
+/*===========================================================================*/
+/*  Frame packing.  Used only for type 0 packets (raw Vorbis data)           */
+/*===========================================================================*/
+
+    if (length < 256 && type == 0) {
+        if (length + stacksize < 256 && stackcount < 15) {
+
+            framestack = realloc (framestack, (stacksize + (length + 1)));
+
+            framestack [stacksize] = length;
+            memcpy (framestack + (stacksize + 1), vorbdata, length);
+            stackcount++;
+            stacksize += (length + 1);
+        }  
+
+        if (length + stacksize > 256 || stackcount > 15) {
+
+            /*  Set Vorbis header flags  */
+            vorbheader -> continuation = 1;
+            vorbheader -> fragment = 1;
+            vorbheader -> type = type;
+            vorbheader -> pkts = stackcount;
+
+            packet = malloc (stacksize + 6);
+
+            memmove (packet, vorbheader, 5);
+            memmove (packet + 6, framestack, stacksize);
+
+            /*  Swap RTP headers from host to network order  */
+            RTPHeaders.sequence = htons (RTPHeaders.sequence);
+            RTPHeaders.timestamp = htonl (RTPHeaders.timestamp);
+
+            sendrtp (&RTPHeaders, rtpsocket, &rtpsock, packet, stacksize + 6);
+
+            /*  Swap headers back to host order  */
+            RTPHeaders.sequence = htons (RTPHeaders.sequence);
+            RTPHeaders.timestamp = ntohl (RTPHeaders.timestamp);
+
+            if (stackcount == 1) 
+                progressmarker (0);
+            else
+                progressmarker (5);
+
+            usleep (sleeptime);
+
+            RTPHeaders.sequence++;
+            RTPHeaders.timestamp += sleeptime;
+
+            stacksize = 0;
+            stackcount = 0;
+
+            free (packet);
+        }   
+        return;
+    } 
+
+/*===========================================================================*/
+/*  Send header packets (under 256 octets) - No Packing                      */
+/*===========================================================================*/
+
+    else if (length < 256) {
+
+        /*  Set Vorbis header flags  */
+        vorbheader -> continuation = 0;
+        vorbheader -> fragment = 1;
+        vorbheader -> type = type;
+        vorbheader -> pkts = 1;
+
+        framesize = (unsigned char) length;
+
+        packet = malloc (length + 6);
+
+        memcpy (packet, vorbheader, 5);
+        memcpy (packet + 5, &framesize, 1);
+        memcpy (packet + 6, vorbdata, length);
+
+        /*  Swap RTP headers from host to network order  */
+        RTPHeaders.sequence = htons (RTPHeaders.sequence);
+        RTPHeaders.timestamp = htonl (RTPHeaders.timestamp);
+
+        sendrtp (&RTPHeaders, rtpsocket, &rtpsock, packet, length + 6);
+
+        /*  Swap headers back to host order  */
+        RTPHeaders.sequence = htons (RTPHeaders.sequence);
+        RTPHeaders.timestamp = ntohl (RTPHeaders.timestamp);
+
+        sleeptime = ((1 / (float) bitrate) * 1000000);
+        usleep (sleeptime);
+
+        RTPHeaders.sequence++;
+        RTPHeaders.timestamp += sleeptime;
+
+        free (packet);
+    }            
+}
+
+/*****************************************************************************/
+/*  Sends RTP packet                                                         */
+/*****************************************************************************/
+
+int sendrtp (struct RTPHeaders *RTPHeaders, int rtpsocket, struct sockaddr_in *sockAddr, const void *packet, int length)
+{
+    int ret;
+
+    char *outbuffer;
+
+    outbuffer = malloc (sizeof (struct RTPHeaders) + length);
+
+    memcpy (outbuffer,  RTPHeaders, sizeof (struct RTPHeaders));
+    memcpy (outbuffer + sizeof (struct RTPHeaders), packet, length);
+
+    ret = sendto (rtpsocket, outbuffer, sizeof (struct RTPHeaders) + length, 0, (struct sockaddr *) sockAddr, sizeof (*sockAddr));
+
+    free (outbuffer);
+    return (ret);
+}
+
+/*****************************************************************************/
+
+int main (int argc, char **argv) 
+{
+    ogg_sync_state oy;
+    ogg_stream_state os;
+    ogg_page og;
+    ogg_packet op;
+  
+    vorbis_info vi; 
+
+    vorbis_comment vc;
+    vorbis_dsp_state vd;
+    vorbis_block vb;
+  
+    char *buffer;
+    int  bytes;
+
+    char *filename;
+    FILE *file;
+    ogg_sync_init (&oy);
+
+    int i = 0;
+    int opt;
+
+    char *ip = "227.0.0.1";
+    unsigned int port = 4044;
+    unsigned int ttl  = 1;
+
+    fprintf (stderr, "||---------------------------------------------------------------------------||\n");
+    fprintf (stderr, "||  Vorbis RTP Server (draft-kerr-avt-vorbis-rtp-04)\n");	  
+
+/*===========================================================================*/
+/*  Command-line args processing                                             */
+/*===========================================================================*/
+
+    if (argc < 2) {
+        fprintf (stderr, "||\n||  No Vorbis file specified.\n");
+        fprintf (stderr, "||  Usage: vorbisrtp [-i ip address] [-p port] [-t ttl] filename\n\n");
+        exit (1);
+    }
+
+    while ((opt = getopt (argc, argv, "i:p:t:")) != -1) {
+        switch (opt)
+	    {
+
+        /*  Set IP address  */
+	    case 'i':
+    	        ip = optarg;
+	        break;
+
+        /*  Set port  */
+	    case 'p':
+	            port = atoi (optarg);
+	        break;
+
+        /*  Set TTL value  */
+	    case 't':
+    	        ttl = atoi (optarg);
+	        break;
+
+        /* Unknown option  */
+	    case '?':
+	            fprintf (stderr, "\n||  Unknown option `-%c'.\n", optopt);
+	        return 1;
+        }
+    }
+
+/*===========================================================================*/
+/*  Init RTP socket                                                          */
+/*===========================================================================*/
+
+    rtpsocket = createsocket (&RTPHeaders, &rtpsock, ip, port, ttl);
+
+/*===========================================================================*/
+/*  Print network details                                                    */
+/*===========================================================================*/
+
+    fprintf (stdout, "||---------------------------------------------------------------------------||\n");
+    fprintf (stdout, "||  Network setup\n");	  
+    fprintf (stdout, "||  IP Address= %s\n", ip);
+    fprintf (stdout, "||  Port = %d\n", port);
+    fprintf (stdout, "||  TTL = %d\n", ttl);
+    fprintf (stdout, "||\n");
+    fprintf (stdout, "||---------------------------------------------------------------------------||\n");
+
+/*===========================================================================*/
+/*  Open Vorbis file                                                         */
+/*===========================================================================*/
+
+    filename = argv [argc - 1];
+    file = fopen (filename, "rb");
+
+    if (file == NULL) {
+        fprintf (stderr, "||  Could not open file %s\n", filename);
+        exit (1);
+    }
+
+    fprintf (stdout, "||  Vorbis setup\n");
+    fprintf (stdout, "||  Filename: %s\n", filename);
+
+    int eos = 0;
+
+    buffer = ogg_sync_buffer (&oy, 4096);
+
+    bytes = fread (buffer, 1, 4096, file);
+
+    ogg_sync_wrote (&oy, bytes);
+    
+    if (ogg_sync_pageout (&oy, &og) != 1) {
+        if (bytes < 4096) {
+            fprintf (stdout, "||  Done\n");
+            exit (0);
+        }
+      
+        fprintf (stderr, "\n||  Input does not appear to be an Ogg bitstream.\n");
+        exit (1);
+    }
+  
+    ogg_stream_init (&os, ogg_page_serialno (&og));
+    
+    vorbis_info_init (&vi);
+    vorbis_comment_init (&vc);
+
+    if (ogg_stream_pagein (&os, &og) < 0) { 
+        fprintf (stderr, "||  Error reading first page of Ogg bitstream data.\n");
+        exit (1);
+    }
+    
+    if (ogg_stream_packetout (&os, &op) != 1) { 
+        fprintf (stderr, "||  Error reading initial header packet.\n");
+        exit (1);
+    }
+    
+    if (vorbis_synthesis_headerin (&vi, &vc, &op) < 0) { 
+        fprintf (stderr, "||  This Ogg bitstream does not contain Vorbis audio data.\n");
+        exit (1);
+    }
+
+/*===========================================================================*/
+/*  Process comment and codebook headers                                     */
+/*===========================================================================*/
+
+    while (i < 2) {
+        while (i < 2) {
+            int result = ogg_sync_pageout (&oy, &og);
+
+        	if (result == 0) break; /* Need more data  */
+
+        	if (result == 1) {
+        	    ogg_stream_pagein (&os, &og); 
+
+                while(i < 2) {
+            	    result = ogg_stream_packetout (&os, &op);
+
+                    if (result == 0) break;
+                    
+                    if (result < 0) {
+                        fprintf (stderr, "||  Corrupt secondary header.  Exiting.\n");
+                        exit (1);
+    	            }
+
+                    vorbis_synthesis_headerin (&vi, &vc, &op);
+                    i++;
+                }
+            }
+        }
+
+        buffer = ogg_sync_buffer (&oy, 4096);
+        bytes = fread (buffer, 1, 4096, file);
+
+        if (bytes == 0 && i < 2) {
+            fprintf (stderr, "||  End of file before finding all Vorbis headers!\n");
+            exit (1);
+        }
+
+        ogg_sync_wrote (&oy, bytes);
+    }
+
+    convsize = 4096 / vi.channels;
+    vorbis_synthesis_init (&vd, &vi);
+    vorbis_block_init (&vd, &vb);
+
+/*===========================================================================*/
+/*  Codebook Ident                                                           */
+/*===========================================================================*/
+
+    VorbisBitfields.cbident = crc32 (sizeof (vd), (char*) &vd);
+
+/*===========================================================================*/
+/*  Print details                                                            */
+/*===========================================================================*/
+
+    fprintf (stdout, "||  Bitstream is %d channel, %ldHz\n", vi.channels, vi.rate);
+    fprintf (stdout, "||  Encoded by: %s\n", vc.vendor);
+    fprintf (stdout, "||  Bitrates: min=%ld - nom=%ld - max=%ld\n", vi.bitrate_lower, vi.bitrate_nominal, vi.bitrate_upper);
+    fprintf (stdout, "||\n");
+    fprintf (stdout, "||---------------------------------------------------------------------------||\n");
+    fprintf (stdout, "||  Processing\n||  ");
+
+/*===========================================================================*/
+/*  Create configuration header                                              */
+/*===========================================================================*/
+
+    configpacket (&VorbisConfig, vorbis_info_blocksize (&vi, 0), vorbis_info_blocksize (&vi, 1), vi);
+
+/*===========================================================================*/
+/*  Create and send codebook                                                 */
+/*===========================================================================*/
+
+    creatertp ((char*) &vd, sizeof (vd), vi.rate, &VorbisBitfields, 2);
+    progressmarker (4);
+
+/*===========================================================================*/
+/*  Read raw Vorbis data and send RTP packet                                 */
+/*===========================================================================*/
+
+    while (!eos) {
+        while (!eos) {
+            int result = ogg_sync_pageout (&oy, &og);
+
+            if (result == 0) break; /* need more data  */
+
+            if (result < 0) {
+                fprintf (stderr, "\n||  Corrupt or missing data in bitstream; continuing....\n||  ");
+            } else {
+                ogg_stream_pagein (&os, &og); 
+
+                while (1) {
+                    result = ogg_stream_packetout (&os, &op);
+
+                    if (result == 0) break; /* need more data  */
+
+                    if (result < 0) {
+                        /* no reason to complain; already complained above  */
+            	    } else {
+                        creatertp (op.packet, op.bytes, vi.rate, &VorbisBitfields, 0);
+            	    }
+                }
+
+                if (ogg_page_eos (&og)) eos = 1;
+            }
+        }
+
+        if (!eos) {
+            buffer = ogg_sync_buffer (&oy, 4096);
+            bytes = fread (buffer, 1, 4096, file);
+
+            ogg_sync_wrote (&oy, bytes);
+    
+            if (bytes == 0) eos = 1;
+        }
+    }
+
+    ogg_stream_clear (&os);
+  
+    vorbis_block_clear (&vb);
+    vorbis_dsp_clear (&vd);
+	vorbis_comment_clear (&vc);
+    vorbis_info_clear (&vi);
+
+    ogg_sync_clear (&oy);
+    fclose (file);
+
+    fprintf (stdout, "\n||---------------------------------------------------------------------------||\n");
+    fprintf (stdout, "||  Done.\n");
+    return (0);
+}
+
+/*****************************************************************************/
+/*  End                                                                      */
+/*****************************************************************************/



More information about the commits mailing list