[xiph-cvs] cvs commit: vorbis-tools/ogg123 buffer.c buffer.h ogg123.c ogg123.h

Kenneth C. Arnold kcarnold at xiph.org
Thu Jun 21 20:55:38 PDT 2001



kcarnold    01/06/21 20:55:37

  Modified:    ogg123   Tag: kcarnold_work buffer.c buffer.h ogg123.c
                        ogg123.h
  Log:
  My late night hacking. Two major things:
  
  1. Buffer fill indication.
  2. Overhaul to buffer semantics, including buffer flushing
  capabilities and a few significant optimizations that should decrease
  CPU usage noticably.

Revision  Changes    Path
No                   revision

No                   revision

1.7.2.1   +67 -10    vorbis-tools/ogg123/buffer.c

Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- buffer.c	2001/06/19 19:42:35	1.7
+++ buffer.c	2001/06/22 03:55:36	1.7.2.1
@@ -5,6 +5,8 @@
  * that program is used in this buffer.
  */
 
+#define DEBUG_BUFFER
+
 #include <sys/types.h>
 #if HAVE_SMMAP
 #include <sys/mman.h>
@@ -20,12 +22,28 @@
 #include "ogg123.h"
 #include "buffer.h"
 
+#ifdef DEBUG_BUFFER
+FILE *debugfile;
+#define DEBUG0(x) do { fprintf (debugfile, x "\n" ); } while (0)
+#define DEBUG1(x, y) do { fprintf (debugfile, x "\n" , y); } while (0)
+#else
+#define DEBUG0(x)
+#define DEBUG1(x, y)
+#endif
+
+void signal_handler (int sig)
+{
+}
+
 /* Initialize the buffer structure. */
 void buffer_init (buf_t *buf, long size)
 {
+  DEBUG0("buffer init");
+  memset (buf, 0, sizeof(*buf));
   buf->status = 0;
   buf->reader = buf->writer = buf->buffer;
   buf->end = buf->buffer + (size - 1);
+  buf->size = size;
 }
 
 /* Main write loop. No semaphores. No deadlock. No problem. I hope. */
@@ -34,24 +52,40 @@
   devices_t *d1;
   signal (SIGINT, SIG_IGN);
 
+  DEBUG0("r: writer_main");
   while (! (buf->status & STAT_SHUTDOWN && buf->reader == buf->writer))
     {
       /* Writer just waits on reader to be done with buf_write.
        * Reader must ensure that we don't deadlock. */
 
-      write (buf->fds[1], "1", 1); /* This identifier could hold a lot
-				    * more detail in the future. */
+      if (buf->reader == buf->writer) {
+	/* this won't deadlock, right...? */
+	DEBUG0("alerting writer");
+	write (buf->fds[1], "1", sizeof(int)); /* This identifier could hold a lot
+						* more detail in the future. */
+      }
 
       if (buf->status & STAT_FLUSH) {
+      flush:
+	DEBUG0("r: buffer flush");
         buf->reader = buf->writer;
         buf->status &= ~STAT_FLUSH;
+	DEBUG1("buf->status = %d", buf->status);
+	write (buf->fds[1], "F", sizeof(int));
       }
+
+      while (buf->reader == buf->writer && !(buf->status & STAT_SHUTDOWN)
+	     && !(buf->status & STAT_FLUSH))
+	DEBUG1("looping on buffer underflow, status is %d", buf->status);
 
-      while (buf->reader == buf->writer && !(buf->status & STAT_SHUTDOWN));
+      if (buf->status & STAT_FLUSH)
+	goto flush; /* eeew... */
 
-      if (buf->reader == buf->writer) break;
+      if (buf->reader == buf->writer)
+	break;
 
       /* devices_write (buf->writer->data, buf->writer->len, d); */
+      DEBUG0("writing chunk");
       {
         d1 = d;
         while (d1 != NULL) {
@@ -60,13 +94,17 @@
         }
       }
 
+      DEBUG0("incrementing pointer");
       if (buf->writer == buf->end)
         buf->writer = buf->buffer;
       else
         buf->writer++;
    }
+  DEBUG0("r: shutting down buffer");
   buf->status = 0;
-  write (buf->fds[1], "2", 1);
+  write (buf->fds[1], "2", sizeof(int));
+  kill (buf->writerpid, SIGHUP);
+  DEBUG0("r: exiting");
   _exit(0);
 }
 
@@ -120,6 +158,11 @@
   shmctl(shmid, IPC_RMID, 0);
 #endif /* HAVE_SMMAP */
 
+#ifdef DEBUG_BUFFER
+  debugfile = fopen ("/tmp/bufferdebug", "w"); /* file can be a pipe */
+  setvbuf (debugfile, NULL, _IONBF, 0);
+#endif
+
   buffer_init (buf, size);
   
   /* Create a pipe for communication between the two processes. Unlike
@@ -132,12 +175,14 @@
       exit (1);
     }
 
-  fcntl (buf->fds[1], F_SETFL, O_NONBLOCK);
   /* write should never block; read should always block. */
+  fcntl (buf->fds[1], F_SETFL, O_NONBLOCK);
 
   fflush (stdout);
   /* buffer flushes stderr, but stderr is unbuffered (*duh*!) */
-  
+
+  signal (SIGHUP, signal_handler);
+
   childpid = fork();
   
   if (childpid == -1)
@@ -151,8 +196,11 @@
       writer_main (buf, d);
       return NULL;
     }
-  else
+  else {
+    buf->writerpid = getpid();
+    buf->readerpid = childpid;
     return buf;
+  }
 }
 
 void submit_chunk (buf_t *buf, chunk_t chunk)
@@ -163,6 +211,7 @@
   FD_ZERO(&set);
   FD_SET(buf->fds[0], &set);
 
+  DEBUG0("submit_chunk");
   /* Wait wait, don't step on my sample! */
   while (!((buf->reader != buf->end && buf->reader + 1 != buf->writer) ||
            (buf->reader == buf->end && buf->writer != buf->buffer)))
@@ -171,24 +220,29 @@
       int ret;
       char t;
       
+      DEBUG0("w: looping on buffer overflow");
       tv.tv_sec = 1;
       tv.tv_usec = 0;
       ret = select (buf->fds[0]+1, &set, NULL, NULL, &tv);
       
-      while (ret-- > 0)
-	read (buf->fds[0], &t, 1);
+      DEBUG1("w: select returned %d", ret);
+      if (ret > 0)
+	read (buf->fds[0], &t, sizeof(int));
     }
               
+  DEBUG0("writing chunk");
   *(buf->reader) = chunk;
   /* do this atomically */
   if (buf->reader == buf->end)
     buf->reader = buf->buffer;
   else
     buf->reader++;
+  DEBUG0("submit_chunk exit");
 }
 
 void buffer_flush (buf_t *buf)
 {
+  DEBUG0("flush buffer");
   buf->status |= STAT_FLUSH;
 }
 
@@ -196,9 +250,11 @@
 {
   struct timeval tv;
 
+  DEBUG0("shutdown buffer");
   buf->status |= STAT_SHUTDOWN;
   while (buf->status != 0)
     {
+      DEBUG0("waiting on reader to quit");
       tv.tv_sec = 1;
       tv.tv_usec = 0;
       select (0, NULL, NULL, NULL, &tv);
@@ -207,4 +263,5 @@
   /* Deallocate the shared memory segment. */
   shmdt(buf);
 #endif /* HAVE_SMMAP */
+  DEBUG0("buffer done.");
 }

1.2.2.1   +5 -0      vorbis-tools/ogg123/buffer.h

Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- buffer.h	2001/06/19 19:42:35	1.2
+++ buffer.h	2001/06/22 03:55:36	1.2.2.1
@@ -5,6 +5,8 @@
 
 #include "ogg123.h"
 
+#include <sys/types.h>
+
 typedef struct chunk_s
 {
   long len; /* Length of the chunk (for if we only got partial data) */
@@ -15,6 +17,9 @@
 {
   char status;       /* Status. See STAT_* below. */
   int fds[2];        /* Pipe file descriptors. */
+  long size;         /* buffer size, for reference */
+  pid_t readerpid;   /* PID of reader process */
+  pid_t writerpid;   /* PID of writer process */
   chunk_t *reader;   /* Chunk the reader is busy with */
   chunk_t *writer;   /* Chunk the writer is busy with */
   chunk_t *end;      /* Last chunk in the buffer (for convenience) */

1.39.2.1  +56 -13    vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.39
retrieving revision 1.39.2.1
diff -u -r1.39 -r1.39.2.1
--- ogg123.c	2001/06/19 19:42:35	1.39
+++ ogg123.c	2001/06/22 03:55:36	1.39.2.1
@@ -14,7 +14,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.39 2001/06/19 19:42:35 kcarnold Exp $
+ last mod: $Id: ogg123.c,v 1.39.2.1 2001/06/22 03:55:36 kcarnold Exp $
 
  ********************************************************************/
 
@@ -122,6 +122,8 @@
     opt.buffer_size = 0;
     opt.delay = 1;
 
+    atexit (buffer_cleanup);
+    signal (SIGINT, signal_quit);
     ao_initialize();
 
     while (-1 != (ret = getopt_long(argc, argv, "b:d:hl:k:o:qvVz",
@@ -226,8 +228,10 @@
       opt.outdevices = current;
     }
 
-    if (buffer != NULL)
+    if (buffer != NULL) {
             buffer_shutdown(buffer);
+            buffer = NULL;
+    }
     
     ao_shutdown();
 
@@ -263,7 +267,13 @@
   old_sig = signal(SIGINT,signal_skipfile);
 }
 
+void signal_quit(int ignored)
+{
+  exit(0);
+}
+
 
+
 void play_file(ogg123_options_t opt)
 {
     /* Oh my gosh this is disgusting. Big cleanups here will include an
@@ -387,7 +397,7 @@
                 exit(1);
 
         if (opt.quiet < 1) {
-	    if (eos && opt.verbose) fprintf (stderr, "\r                                                      \r\n");
+	    if (eos && opt.verbose) fprintf (stderr, "\r                                                                          \r\n");
             for (i = 0; i < vc->comments; i++) {
                 char *cc = vc->user_comments[i];	/* current comment */
                 int i;
@@ -478,29 +488,43 @@
                       c_sec = u_pos - 60 * c_min;
                       r_min = (long) (u_time - u_pos) / (long) 60;
                       r_sec = (u_time - u_pos) - 60 * r_min;
-		      fprintf(stderr,
-			      "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f   \r",
-			      c_min, c_sec, r_min, r_sec, t_min, t_sec,
-			      (float) ov_bitrate_instant(&vf) / 1000.0F);
+		      if (buffer)
+			fprintf(stderr,
+				"\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%%   \r",
+				c_min, c_sec, r_min, r_sec, t_min, t_sec,
+				(double) ov_bitrate_instant(&vf) / 1000.0F,
+				buffer_full(buffer)*100.0F);
+		      else
+			fprintf(stderr,
+				"\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f   \r",
+				c_min, c_sec, r_min, r_sec, t_min, t_sec,
+				(double) ov_bitrate_instant(&vf) / 1000.0F);
                     } else {
                       /* working around a bug in vorbisfile */
                       u_pos = (double) ov_pcm_tell(&vf) / (double) vi->rate;
                       c_min = (long) u_pos / (long) 60;
                       c_sec = u_pos - 60 * c_min;
-		      fprintf(stderr,
-			      "\rTime: %02li:%05.2f, Bitrate: %.1f   \r",
-			      c_min, c_sec,
-			      (float) ov_bitrate_instant (&vf) / 1000.0F);
+		      if (buffer)
+			fprintf(stderr,
+				"\rTime: %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%%   \r",
+				c_min, c_sec,
+				(float) ov_bitrate_instant (&vf) / 1000.0F,
+				buffer_full(buffer)*100.0F);
+		      else
+			fprintf(stderr,
+				"\rTime: %02li:%05.2f, Bitrate: %.1f   \r",
+				c_min, c_sec,
+				(float) ov_bitrate_instant (&vf) / 1000.0F);
                     }
                 }
             }
         }
     }
-
+    
     alarm(0);
     signal(SIGALRM,SIG_DFL);
     signal(SIGINT,old_sig);
-
+    
     ov_clear(&vf);
 
     if (opt.quiet < 1)
@@ -587,4 +611,23 @@
     *buffer = fork_writer (opt->buffer_size, opt->outdevices);
   
     return 0;
+}
+
+double buffer_full (buf_t* buf) {
+  chunk_t *reader = buf->reader; /* thread safety... */
+  int chunks;
+
+  if (reader > buf->writer)
+    chunks = (reader - buf->writer);
+  else
+    chunks = (buf->end - reader) + (buf->writer - buf->buffer);
+  return (double) chunks / buf->size;
+}
+
+void buffer_cleanup (void) {
+  if (buffer) {
+    buffer_flush (buffer);
+    buffer_shutdown (buffer);
+    buffer = NULL;
+  }
 }

1.7.2.1   +4 -0      vorbis-tools/ogg123/ogg123.h

Index: ogg123.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.h,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- ogg123.h	2001/06/19 17:15:32	1.7
+++ ogg123.h	2001/06/22 03:55:36	1.7.2.1
@@ -28,6 +28,7 @@
   signed short int quiet;     /* Be quiet (no title) */
   double seekpos;             /* Amount to seek by */
   FILE *instream;             /* Stream to read from. */
+  char *default_device;       /* default device for playback */
   devices_t *outdevices;      /* Streams to write to. */
   int buffer_size;            /* Size of the buffer in chunks. */
   int rate, channels;         /* playback params for opening audio devices */
@@ -47,5 +48,8 @@
 int get_tcp_socket(void); /* Will be going soon. */
 FILE *http_open(char *server, int port, char *path); /* ditto */
 int open_audio_devices(ogg123_options_t *opt, int rate, int channels, buf_t ** buffer);
+double buffer_full (buf_t* buffer);
+void buffer_cleanup (void);
+void signal_quit (int ignored);
 
 #endif /* !defined(__OGG123_H) */

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list